标签:
题意:
每次操作区间每个数进行一种(&或|、或^ )给定的一个数,到sum时统计给定区间的和。
分析:
这个题让我觉得我的思维很不活跃,对懒惰标记理解,还远远不够,通过这道题我对懒惰标记加深了不少。
经过各种操作和区间会变成相同数都相邻的情况,若在操作会变成另一个相同数。
选区间内相同数字为懒惰标记进行更新。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<1|1 #define All 1,N,1 #define N 1000100 #define read freopen("in.txt", "r", stdin) const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; int same[N*4],n,q,a[N]; void pushup(int rt){ if(same[rt<<1]==same[rt<<1|1]&&same[rt<<1]!=-1){ same[rt]=same[rt<<1]; } } void pushdown(int rt){ if(same[rt]!=-1){ same[rt<<1]=same[rt<<1|1]=same[rt]; same[rt]=-1; } } void build(int l,int r,int rt){ same[rt]=-1; if(l==r){ same[rt]=a[l]; return; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } void update(int op,int opn,int L,int R,int l,int r,int rt){ if(L<=l&&R>=r&&same[rt]!=-1){ if(op==0) same[rt]&=opn; else if(op==1) same[rt]|=opn; else same[rt]^=opn; return; } pushdown(rt); int m=(l+r)>>1; if(L<=m)update(op,opn,L,R,lson); if(R>m)update(op,opn,L,R,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt){ if(L<=l&&R>=r&&same[rt]!=-1){ return (r-l+1)*same[rt]; } pushdown(rt); int num=0; int m=(l+r)>>1; if(L<=m)num+=query(L,R,lson); if(R>m)num+=query(L,R,rson); pushup(rt); return num; } int main() { int t; scanf("%d",&t); char ans[5]; while(t--){ scanf("%d%d",&n,&q); for(int i=1;i<=n;++i) scanf("%d",&a[i]); build(1,n,1); int x,y,p; while(q--){ scanf("%s",ans); if(ans[0]==‘A‘){ scanf("%d%d%d",&p,&x,&y); update(0,p,x+1,y+1,1,n,1); } else if(ans[0]==‘O‘){ scanf("%d%d%d",&p,&x,&y); update(1,p,x+1,y+1,1,n,1); } else if(ans[0]==‘X‘){ scanf("%d%d%d",&p,&x,&y); update(2,p,x+1,y+1,1,n,1); } else{ scanf("%d%d",&x,&y); printf("%d\n",query(x+1,y+1,1,n,1)); } } } return 0; }
FZU 2105-Digits Count(线段树延时标记)
标签:
原文地址:http://www.cnblogs.com/zsf123/p/4716632.html