【线段树】 FZU 2105 Digits Count
来源:互联网 发布:赵敏 情趣 知乎 编辑:程序博客网 时间:2024/05/22 12:36
点击打开链接
因为单个数最大为15 所以可以将一个数分成四位
因为SUM 和OR 操作会霸气的将区间内变成全0 或全1
所以需要清空col数组
而XOR不需要
Pushdown时同理,而且需要注意顺序。因为只有(先SUM或OR 再 XOR操作)这种可能 才会在同一个结点上有两个标记
#include <cstdio>#include <cstring>#include <cstdlib>#include <string>#include <iostream>#include <algorithm>#include <sstream>#include <cmath>using namespace std;#include <queue>#include <stack>c#include <set>#include <vector>#include <deque>#include <map>#define cler(arr, val) memset(arr, val, sizeof(arr))#pragma comment(linker, "/STACK:102400000,102400000")typedef long long LL;const int MAXN = 1020200;const int MAXM = 140000;const int INF = 0x3f3f3f3f;const int mod = 1000000007;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int sum[MAXN<<2][4],col[4][3][MAXN<<2],a,num;void pushdown(int rt,int x){ for(int i=0;i<4;i++) { if(col[i][1][rt])//or { col[i][0][rt<<1]=0; col[i][0][rt<<1|1]=0; col[i][1][rt<<1]=1; col[i][1][rt<<1|1]=1; col[i][2][rt<<1]=0; col[i][2][rt<<1|1]=0; sum[rt<<1][i]=x-(x>>1); sum[rt<<1|1][i]=x>>1; } else if(col[i][2][rt])//and { col[i][0][rt<<1]=0; col[i][0][rt<<1|1]=0; col[i][1][rt<<1]=0; col[i][1][rt<<1|1]=0; col[i][2][rt<<1]=1; col[i][2][rt<<1|1]=1; sum[rt<<1][i]=0; sum[rt<<1|1][i]=0; } if(col[i][0][rt])//xor { col[i][0][rt<<1]^=1; col[i][0][rt<<1|1]^=1; sum[rt<<1][i]=(x-(x>>1))-sum[rt<<1][i]; sum[rt<<1|1][i]=(x>>1)-sum[rt<<1|1][i]; } col[i][0][rt]=0; col[i][1][rt]=0; col[i][2][rt]=0; }}void pushup(int rt){ for(int i=0;i<4;i++) sum[rt][i]=sum[rt<<1][i]+sum[rt<<1|1][i];}void build(int l,int r,int rt){ for(int i=0;i<4;i++) col[i][0][rt]=col[i][1][rt]=col[i][2][rt]=0; if(l==r) { scanf("%d",&a); for(int i=0;i<4;i++) sum[rt][i]=(a&(1<<i))?1:0; return ; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt);}void update(int L,int R,int l,int r ,int rt,int x){ if(L<=l&&r<=R) { for(int i=0;i<4;i++) { int c=(x&(1<<i))?1:0; if(num==2&&c==0)//and { sum[rt][i]=0; col[i][0][rt]=0; col[i][1][rt]=0; col[i][num][rt]=1; } else if(num==1&&c)//or { sum[rt][i]=r-l+1; col[i][0][rt]=0; col[i][num][rt]=1; col[i][2][rt]=0; } else if(num==0&&c)//xor { sum[rt][i]=(r-l+1)-sum[rt][i]; col[i][num][rt]^=1; } } return ; } pushdown(rt,r-l+1); int m=(l+r)>>1; if(L<=m) update(L,R,lson,x); if(m<R) update(L,R,rson,x); pushup(rt);}int query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) { int val=0; for(int i=0;i<4;i++) val+=sum[rt][i]*(1<<i); return val; } pushdown(rt,r-l+1); int ans=0; int m=(l+r)>>1; if(L<=m) ans+=query(L,R,lson); if(m<R) ans+=query(L,R,rson); return ans;}int main(){#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout);#endif int n,m,t,l,r; char s[10]; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); build(1,n,1); while(m--) { scanf("%s",s); if(s[0]=='S') { scanf("%d%d",&l,&r); printf("%d\n",query(l+1,r+1,1,n,1)); } else { int x; scanf("%d%d%d",&x,&l,&r); if(s[0]=='X') num=0; if(s[0]=='O') num=1; if(s[0]=='A') num=2; update(l+1,r+1,1,n,1,x); } } } return 0;}
0 0
- fzu 2105 Digits Count 线段树
- 【线段树】 FZU 2105 Digits Count
- 【FZU】2105 Digits Count 线段树
- 【线段树】 FZU 2105 Digits Count
- FZU 2105 Digits Count(线段树)
- FZU-2105 Digits Count(线段树)
- FZU 2105 Digits Count(线段树区间修改)
- fzu 2105 Digits Count (线段树区间更新)
- [FZU 2105 Digits Count] 线段树区间的复合操作
- fzu 2105 Digits Count
- FZU 2105 Digits Count
- FZU 2105 Digits Count
- FZU 2105 Digits Count
- FZU 2105 Digits Count
- fzu 2105——Digits Count
- FZU 2105 Digits Count 区间更新
- [FOJ 2105][Vjudge 35179] Digits Count [线段树]
- FZU2105-Digits Count(线段树区间)
- [转]C++程序设计之四书五经
- oc 运行时方法(一)
- 第12条: 复制整个对象,不要遗漏任一部分
- 输入外挂
- 【Linux】Ubuntu下C语言访问MySQL数据库入门
- 【线段树】 FZU 2105 Digits Count
- RabbitMQ(一)概念
- 利用FTM输出PWM波形是这么一回事!
- 母函数模板分析
- ios中五种回调方式
- Mac OS X下各种文件编码的转换方法
- 看描述
- hibernate多对多关联双向一对多实现
- 最大正向匹配分词MM