您的位置:首页 > 其它

【线段树】 FZU 2105 Digits Count

2014-12-06 21:56 423 查看
点击打开链接

因为单个数最大为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|1
int 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树