【洛谷】P4883 mzf的考验

【洛谷】P4883 mzf的考验

最近忽然放弃治疗开始随机跳题了

感觉还行

就是必须吸氧感觉有点糟糕。。。

这题翻转和求和都是平衡树基本操作,那个异或可以通过维护树中\(2\)进制下第\(2^{i}\)位的\(1\)的个数,即可\(O(\log d)\)快速维护

当敲板子玩了

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define ba 47
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 +c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
mt19937 rnd(20020328); 
struct node {
    int pri;
    int lc,rc,siz;
    int cnt[20],d;
    int64 sum,val;
    bool rev;
}tr[MAXN];
int N,M,rt;
int a[MAXN];
#define lc(u) tr[u].lc
#define rc(u) tr[u].rc
#define sum(u) tr[u].sum
void update(int u) {
    for(int j = 0 ; j < 20 ; ++j) {
	tr[u].cnt[j] = ((tr[u].val >> j) & 1) + tr[lc(u)].cnt[j] + tr[rc(u)].cnt[j];
    }
    tr[u].sum = tr[u].val + tr[lc(u)].sum + tr[rc(u)].sum;
    tr[u].siz = 1 + tr[lc(u)].siz + tr[rc(u)].siz;
}
void xorit(int u,int d) {
    tr[u].val ^= d;tr[u].d ^= d;
    for(int j = 0 ; j < 20 ; ++j) {
	if(d >> j & 1) {
	    tr[u].sum -= 1LL * tr[u].cnt[j] * (1 << j);
	    tr[u].sum += 1LL * (tr[u].siz - tr[u].cnt[j]) * (1 << j);
	    tr[u].cnt[j] = tr[u].siz - tr[u].cnt[j]; 
	}
    }
    
}
void Rev(int u) {
    tr[u].rev ^= 1;
    swap(lc(u),rc(u));
}
void pushdown(int u) {
    if(tr[u].d) {
	if(lc(u)) xorit(lc(u),tr[u].d);
	if(rc(u)) xorit(rc(u),tr[u].d);
	tr[u].d = 0;
    }
    if(tr[u].rev) {
	if(lc(u)) Rev(lc(u));
	if(rc(u)) Rev(rc(u));
	tr[u].rev = 0;
    }
}
int Merge(int u,int v) {
    if(!u) return v;
    if(!v) return u;
    pushdown(u);pushdown(v);
    if(tr[u].pri > tr[v].pri) {
	tr[u].rc = Merge(tr[u].rc,v);
	update(u);
	return u;
    }
    else {
	tr[v].lc = Merge(u,tr[v].lc);
	update(v);
	return v;
    }
}
void Split(int u,int &L,int &R,int s) {
    if(u == 0) {L = R = 0;return;}
    int t = tr[lc(u)].siz + 1;
    pushdown(u);
    if(s >= t) {
	L = u;
	Split(tr[u].rc,tr[L].rc,R,s - t);
	update(L);
    }
    else {
	R = u;
	Split(tr[u].lc,L,tr[R].lc,s);
	update(R);
    }
}
void Modify(int l,int r,int d) {
    int L,R,p;
    Split(rt,L,R,l - 1);
    Split(R,p,R,r - l + 1);
    xorit(p,d);
    rt = Merge(L,p);rt = Merge(rt,R);
}
void Rev_Range(int l,int r) {
    int L,R,p;
    Split(rt,L,R,l - 1);
    Split(R,p,R,r - l + 1);
    Rev(p);
    rt = Merge(L,p);rt = Merge(rt,R);
}
int64 Query(int l,int r) {
    int L,R,p;
    Split(rt,L,R,l - 1);
    Split(R,p,R,r - l + 1);
    int64 res = tr[p].sum;
    rt = Merge(L,p);rt = Merge(rt,R);
    return res;
}

void Solve() {
    read(N);read(M);
    for(int i = 1 ; i <= N ; ++i) {
	read(a[i]);
	tr[i].pri = rnd();tr[i].sum = a[i];tr[i].val = a[i];
	for(int j = 0 ; j < 20 ; ++j) {
	    tr[i].cnt[j] = (a[i] >> j) & 1;
	}
	tr[i].siz = 1;
	rt = Merge(rt,i);
    }
    int opt,l,r,d;
    for(int i = 1 ; i <= M ; ++i) {
	read(opt);read(l);read(r);
	if(opt == 1) Rev_Range(l,r);
	else if(opt == 2) {read(d);Modify(l,r,d);}
	else {out(Query(l,r));enter;}
    }
}
int main(){
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif

    Solve();
}
posted @ 2019-06-12 08:48  sigongzi  阅读(198)  评论(0编辑  收藏  举报