RE求助
查看原帖
RE求助
222865
迟暮天复明心華楼主2020/8/24 19:28
#include<stdio.h>
#define reg register
#define ri reg int
#define rep(i, x, y) for(ri i = x; i <= y; ++i)
#define nrep(i, x, y) for(ri i = x; i >= y; --i)
#define DEBUG 1
#define ll long long
#define max(i, j) (i) > (j) ? (i) : (j)
#define min(i, j) (i) < (j) ? (i) : (j)
struct IO {
	#define MAXSIZE (1 << 20)
	#define isdigit(x) (x >= '0' && x <= '9')
	char buf[MAXSIZE], *p1, *p2;
	char pbuf[MAXSIZE], *pp;
	#if DEBUG
	#else
		IO() : p1(buf), p2(buf), pp(pbuf) {}
		~IO() {
			fwrite(pbuf, 1, pp - pbuf, stdout);
		}
	#endif
	inline char gc() {
		#if DEBUG
    		return getchar();
		#endif
    	if(p1 == p2)
			p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin);
    	return p1 == p2 ? ' ' : *p1++;
	}
	inline bool blank(char ch) {
    	return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
	}
	template <class T>
	inline void read(T &x) {
    	register double tmp = 1;
    	register bool sign = 0;
    	x = 0;
    	register char ch = gc();
    	for(; !isdigit(ch); ch = gc())
    		if(ch == '-') sign = 1;
    	for(; isdigit(ch); ch = gc())
			x = x * 10 + (ch - '0');
    	if(ch == '.')
			for(ch = gc(); isdigit(ch); ch = gc())
        		tmp /= 10.0, x += tmp * (ch - '0');
    	if(sign) x = -x;
	}
	inline void read(char *s) {
		register char ch = gc();
		for(; blank(ch); ch = gc());
		for(; !blank(ch); ch = gc())
			*s++ = ch;
    	*s = 0;
	}
	inline void read(char &c) {
    	for(c = gc(); blank(c); c = gc());
	}
	inline void push(const char &c) {
		#if DEBUG
    		putchar(c);
		#else
    		if(pp - pbuf == MAXSIZE) {
				fwrite(pbuf, 1, MAXSIZE, stdout);
				pp = pbuf;
			}
    		*pp++ = c;
		#endif
	}
	template <class T>
	inline void write(T x) {
    	if(x < 0) {
			x = -x;
			push('-');
		}
    	static T sta[35];
    	T top = 0;
    	do {
			sta[top++] = x % 10;
			x /= 10;
    	}while(x);
    	while(top)
			push(sta[--top] + '0');
	}
	template <class T>
	inline void write(T x, char lastChar) {
    	write(x);
		push(lastChar);
	}
} io;
ll n, a[200010], d[600000], b[600000];
char s[200010];
void build(ll l, ll r, ll p) { /*建树*/
    ll m = (l + r) >> 1; /*将树分成左子树和右子树*/
    if(l == r) { /*这棵树只有一个节点*/
        d[p] = a[l]; /*将节点的值赋进去*/
        return;
    }
    build(l, m, p << 1); /*递归建左子树*/
	build(m + 1, r, (p << 1) | 1); /*递归建右子树*/
    d[p] = d[p << 1] + d[(p << 1) | 1]; /*父亲节点管理两个孩子节点*/
}
void update(ll l, ll r, ll s, ll t, ll p) { /*将l~r区间内每一个数加上c*/
	ll m = (s + t) >> 1;
    if(b[p]) { /*如果已经有懒标记,且值没有下落,那么将原来的标记去除,权值下落*/
        ri len = m - s + 1;
		d[p << 1] = (len - (len >> 1)) - d[p << 1];
		d[(p << 1) | 1] = (len >> 1) - d[(p << 1) | 1];
        b[p << 1] ^= 1;
		b[(p << 1) | 1] ^= 1;
    }
    b[p] = 0; /*当前节点的懒标记随着权值已经下落,所以要清空*/
    if(l <= m) update(l, r, s, m, p << 1); /*如果需要更改左子树,那么递归*/
    if(r > m) update(l, r, m + 1, t, (p << 1) | 1); /*如果需要更改右子树,那么递归*/
    d[p] = d[p << 1] + d[(p << 1) | 1]; /*最后将孩子的数据汇总*/
}
ll getsum(ll l, ll r, ll s, ll t, ll p) { /*询问l~r节点权值之和*/
    ll m = (s + t) >> 1, sum = 0;
    if(l >= s && t <= r) return d[p]; /*这一块全部在查询范围之内,那么直接累加,无需递归*/
    if(b[p]) { /*如果已经有懒标记,且值没有下落,那么将原来的标记去除,权值下落*/
        ri len = m - s + 1;
		d[p << 1] = (len - (len >> 1)) - d[p << 1];
		d[(p << 1) | 1] = (len >> 1) - d[(p << 1) | 1];
        b[p << 1] ^= 1;
		b[(p << 1) | 1] ^= 1;
    }
    b[p] = 0; /*前节点的懒标记随着权值已经下落,所以要清空*/
    if(l <= m) sum = getsum(l, r, s, m, p << 1); /*如果需要询问左子树,那么递归*/
    if(r > m) sum += getsum(l, r, m + 1, t, (p << 1) | 1); /*如果需要询问右子树,那么递归*/
    return sum; /*总和汇总*/
}
int main() {
    ll q, i1, i2, i3, l, r; /*q:询问个数 i1:操作类型 i2,i3:操作的左右端点 i4:操作1中的k*/
    io.read(n), io.read(q);
    rep(i, 1, n) io.read(s[i]), a[i] = s[i] - '0';
    build(1, n, 1); /*读入权值后建树*/
    while(q--) {
        io.read(i1), io.read(i2), io.read(i3);
        if(i1 == 1) io.write(getsum(i2, i3, 1, n, 1), '\n'); /*操作2,询问总和*/
        else {
			update(i2, i3, 1, n, 1); /*操作1,调整*/
        }
    }
}

注释是从线段树模板一里面搬过来的的,所以有所不同.

2020/8/24 19:28
加载中...