hdu 4391

          题目链接

  典型的sqrt(n)分块题目, 不过是个插段问段, 做法还是大同小异。。。。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>

using namespace std;

const int sz = 400;

inline int readint() {
	char c = getchar();
	while (!isdigit(c)) c = getchar();

	int x = 0;
	while (isdigit(c)) {
		x = x * 10 + c - '0';
		c = getchar();
	}

	return x;
}

struct Block {
	int A[300][sz + 1], B[300][sz + 1];
	int size[305];
	int lazy[305];
	int n, row;

	void init(int n) {
		this->n = n;
		row = 0;
		memset(size, 0, sizeof(size));
		int r = 0, c = 0;
		for (int i = 0; i < n; i++) {
			scanf("%d", &A[r][c]);
			B[r][c] = A[r][c];
			size[r]++;
			c++;
			if (c == sz) {
				c = 0;
				r++;
			}
		}
		row = r + 1;
		for (int i = 0; i < row; i++) {
			sort(B[i], B[i] + size[i]);
			lazy[i] = -1;
		}
	}

	void modify(int l, int r, int x) {
		int r1 = l / sz, r2 = r / sz;
		int c1 = l % sz, c2 = r % sz;
		
		if (r1 == r2) {
			if (lazy[r1] == -1) {
				while (c1 <= c2) {
					A[r1][c1] = x;
					c1++;
				}
			}
			else {
				fill(A[r1], A[r1] + size[r1], lazy[r1]);
				while (c1 <= c2) {
					A[r1][c1] = x;
					c1++;
				}
				lazy[r1] = -1;	
			}

			copy(A[r1], A[r1] + size[r1], B[r1]);
			sort(B[r1], B[r1] + size[r1]);
		}
		else {
			int tmp = size[r1];

			if (lazy[r1] == -1) {
				while (c1 < tmp) {
					A[r1][c1] = x;
					c1++;
				}
				copy(A[r1], A[r1] + size[r1], B[r1]);
				sort(B[r1], B[r1] + size[r1]);	
			}
			else {					
				fill(A[r1], A[r1] + size[r1], lazy[r1]);
				while (c1 < tmp) {
					A[r1][c1] = x;
					c1++;
				}
				lazy[r1] = -1;	
				copy(A[r1], A[r1] + size[r1], B[r1]);
				sort(B[r1], B[r1] + size[r1]);
			}

			r1++;

			if (lazy[r2] == -1) {
				while (c2 >= 0) {
					A[r2][c2] = x;
					c2--;
				}
				copy(A[r2], A[r2] + size[r2], B[r2]);
				sort(B[r2], B[r2] + size[r2]);
			}
			else {					
				fill(A[r2], A[r2] + size[r2], lazy[r2]);
				while (c2 >= 0) {
					A[r2][c2] = x;
					c2--;
				}
				lazy[r2] = -1;	
				copy(A[r2], A[r2] + size[r2], B[r2]);
				sort(B[r2], B[r2] + size[r2]);
			}

			while (r1 < r2) {
				lazy[r1] = x;
				r1++;
			}
		}
	}

	int query(int l, int r, int x) {
		int r1 = l / sz, r2 = r / sz;
		int c1 = l % sz, c2 = r % sz;
		int res = 0;
		if (r1 == r2) {
			if (lazy[r1] == -1) {					
				while (c1 <= c2) {
					if (A[r1][c1] == x) res++;
					c1++;
				}
			}
			else {
				res += lazy[r1] == x ? c2 - c1 + 1 : 0;
			}
		}
		else {
			int tmp = size[r1];

			if (lazy[r1] == -1) {					
				while (c1 < tmp) {
					if (A[r1][c1] == x) res++;
					c1++;
				}
			}
			else {
				res += lazy[r1] == x ? tmp - c1 : 0;
			}

			r1++;

			if (lazy[r2] == -1) {
				while (c2 >= 0) {
					if (A[r2][c2] == x) res++;
					c2--;
				}	
			}
			else {
				res += lazy[r2] == x ? c2 + 1 : 0;
			}

			while (r1 < r2) {
				if (lazy[r1] == -1)
					res += upper_bound(B[r1], B[r1] + size[r1], x) 
						- lower_bound(B[r1], B[r1] + size[r1], x);
				else
					res += lazy[r1] == x ? size[r1] : 0;
				r1++;	
			}
		}

		return res;
	}
}sol;

int main() {
	int n, m, c, l, r, op;

	while (~scanf("%d%d", &n, &m)) {
		sol.init(n);
		while (m--) {
			//op = readint(), l = readint(), r = readint(), c = readint();
			scanf("%d%d%d%d", &op, &l, &r, &c);
			if (op == 1)
				sol.modify(l, r, c);
			else
				printf("%d\n", sol.query(l, r, c));
		}
	}	

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值