【线段树】 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;
}
因为单个数最大为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;
}
相关文章推荐
- 【线段树】 FZU 2105 Digits Count
- FZU 2105 Digits Count(线段树区间修改)
- FZU2105-Digits Count(线段树区间)
- [FZU 2105 Digits Count] 线段树区间的复合操作
- fzu 2105 Digits Count ( 线段树 ) from 第三届福建省大学生程序设计竞赛
- FZU 2105 位运算 (线段树)
- FZU 2105 Digits Count(线段树)
- FZU 2105 Digits Count(线段树)
- FZU2105-Digits Count
- FZU - 2105 Digits Count (线段树成段更新)
- 位运算 FZU - 2105 纯暴力(水,本来应该是线段树)
- fzu 2105 Digits Count
- 【FZU】2105 Digits Count 线段树
- FZU 2105 Digits Count
- FZU2105 Digits Count(经典 线段树)
- FZU 2105 Digits Count
- FZU 2105-Digits Count(线段树延时标记)
- FZU Problem 2105 Digits Count线段树之延迟更新(插线取线)
- fzu 2105 线段树经典题目
- FZU-2105 Digits Count(线段树)