[cogs2638]数列操作ψ(双标记线段树)
题目大意:给定一个数列a,你需要支持的操作:区间and,区间or,询问区间最大值
解题关键:
1、双标记线段树,注意优先级(超时)
当涉及多重标记时,定义出标记的优先级,修改操作时用优先级高(先下放)的修正优先级低(后下放)的来保证标记的正确性。
同时维护了区间and,区间or
https://blog.csdn.net/PhantomAgony/article/details/78810369
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> #define MAXN 100010 #define INF 0x7fffffff #define lc rt<<1 #define rc rt<<1|1 namespace IO{ char buf[1<<15],*fs,*ft; inline char gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;} inline int qr(){ int x=0,rev=0,ch=gc(); while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=gc();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();} return rev?-x:x;} }using namespace IO; using namespace std; int N,Q,tago[MAXN<<2],taga[MAXN<<2],vo[MAXN<<2],va[MAXN<<2],ma[MAXN<<2],a[MAXN]; inline void Up(int rt){ vo[rt]=vo[lc]|vo[rc];va[rt]=va[lc]&va[rc]; ma[rt]=max(ma[lc],ma[rc]); } inline void PutAnd(int rt,int x){//双标记模板题 taga[rt]&=x;tago[rt]&=x; ma[rt]&=x;vo[rt]&=x;va[rt]&=x; } inline void PutOr(int rt,int x){ tago[rt]|=x; ma[rt]|=x;vo[rt]|=x;va[rt]|=x; } inline void Down(int rt){ if(taga[rt]^INF){ PutAnd(lc,taga[rt]); PutAnd(rc,taga[rt]); taga[rt]=INF; } if(tago[rt]){ PutOr(lc,tago[rt]); PutOr(rc,tago[rt]); tago[rt]=0; } } void Build(int l,int r,int rt){ taga[rt]=INF; if(l==r){va[rt]=vo[rt]=ma[rt]=a[l];return;} int mid=(l+r)>>1; Build(l,mid,lc); Build(mid+1,r,rc); Up(rt); } void Modify(int L,int R,int l,int r,int rt,int x,bool flag){ if(L<=l&&R>=r){ if(flag){//区间& if(((x^INF)&(va[rt]|(vo[rt]^INF)))==(x^INF)){//都为1或都为0 PutAnd(rt,x); return; } } else{//区间| if((x&(va[rt]|(vo[rt]^INF)))==x){ PutOr(rt,x); return; } } } Down(rt); int mid=l+r>>1; if(L<=mid)Modify(L,R,l,mid,lc,x,flag); if(R>mid)Modify(L,R,mid+1,r,rc,x,flag); Up(rt); } int Query(int L,int R,int l,int r,int rt){ if(L<=l&&R>=r)return ma[rt]; int mid=(l+r)>>1,ret=0; Down(rt); if(L<=mid)ret=Query(L,R,l,mid,lc); if(R>mid)ret=max(ret,Query(L,R,mid+1,r,rc)); return ret; } int op,x,y,z; int main(){ freopen("series_wei.in","r",stdin); freopen("series_wei.out","w",stdout); N=qr();Q=qr(); for(int i=1;i<=N;i++)a[i]=qr(); Build(1,N,1); while(Q--){ op=qr();x=qr();y=qr(); if(op==1)z=qr(),Modify(x,y,1,N,1,z,1); else if(op==2)z=qr(),Modify(x,y,1,N,1,z,0); else printf("%d\n",Query(x,y,1,N,1)); } return 0; }
2、一个same维护区间内相同的位
#include <cstdio> #include <cstring> #include <algorithm> #define inf 0x3f3f3f3f using namespace std; const int maxn = 100010; const int bas = 0x7fffffff; int T[maxn<<2],lazy[maxn<<2],sam[maxn<<2]; int a[maxn]; inline void update(int rt){ T[rt]=max(T[rt<<1],T[rt<<1|1]); sam[rt]=(sam[rt<<1]&sam[rt<<1|1])&(~(T[rt<<1]^T[rt<<1|1])); } inline void pushdown(int rt){ if(!lazy[rt]) return ; T[rt<<1]+=lazy[rt];lazy[rt<<1]+=lazy[rt]; T[rt<<1|1]+=lazy[rt];lazy[rt<<1|1]+=lazy[rt]; lazy[rt]=0; } void build(int rt,int l,int r){ if(l==r){ T[rt]=a[l]; sam[rt]=bas;//全1 return; } int mid=l+r>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); update(rt); } int L,R,val,tmp; inline bool check_a(int rt){ tmp=(val^bas); return (tmp&sam[rt])==tmp; } void modify_a(int rt,int l,int r){ if(L<=l&&r<=R&&check_a(rt)){ tmp=(T[rt]&val)-T[rt]; lazy[rt]+=tmp; T[rt]+=tmp; return; } pushdown(rt); int mid=l+r>>1; if(L<=mid) modify_a(rt<<1,l,mid); if(R>mid) modify_a(rt<<1|1,mid+1,r); update(rt); } void modify_o(int rt,int l,int r){ if(L<=l&&r<=R&&(sam[rt]&val)==val){ tmp=(T[rt]|val)-T[rt]; lazy[rt]+=tmp; T[rt]+=tmp; return; } int mid=l+r>>1; pushdown(rt); if(L<=mid) modify_o(rt<<1,l,mid); if(R>mid) modify_o(rt<<1|1,mid+1,r); update(rt); } int query(int rt,int l,int r){ if(L<=l&&r<=R) return T[rt]; pushdown(rt); int mid=l+r>>1,res=0; if(L<=mid) res=max(res,query(rt<<1,l,mid)); if(R>mid) res=max(res,query(rt<<1|1,mid+1,r)); return res; } int main(){ freopen("series_wei.in","r",stdin); freopen("series_wei.out","w",stdout); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",a+i); build(1,1,n); int opt; while(m--){ scanf("%d%d%d",&opt,&L,&R); if(opt == 1) scanf("%d",&val),modify_a(1,1,n); else if(opt == 2) scanf("%d",&val),modify_o(1,1,n); else printf("%d\n",query(1,1,n)); } return 0; }