题意:
就是给你两个操作,一种是查询l到r的和,一种是让l到r都异或X。
思考:
就是建立20线段树,看看每一位有多少个1就行了。
同时类似的题目有区间或:RMQ
还有区间与:And RMQ
代码:
区间异或代码:
int T,n,m,k;
int va[N];
int cnt[N];
struct Node{
int L,R;
int laz;
int sum;
};
struct segtree
{
int now;
Node t[4*N];
void pushdown(int node)
{
int laz = t[node].laz;
if(laz)
{
t[node_l].laz ^= laz;
t[node_l].sum = (t[node_l].R-t[node_l].L+1)-t[node_l].sum;
t[node_r].laz ^= laz;
t[node_r].sum = (t[node_r].R-t[node_r].L+1)-t[node_r].sum;
t[node].laz ^= 1;
}
return ;
}
void build(int node,int l,int r)
{
t[node].L = l,t[node].R = r;
if(l==r)
{
t[node].sum = (va[l]>>now&1);
return ;
}
int mid = l+r>>1;
build(node_l,l,mid);build(node_r,mid+1,r);
t[node].sum = t[node_l].sum+t[node_r].sum;
}
void update(int node,int l,int r,int value)
{
if(t[node].L>=l&&t[node].R<=r)
{
t[node].sum = (t[node].R-t[node].L+1)-t[node].sum;
t[node].laz ^= value;
return ;
}
pushdown(node);
int mid = (t[node].L+t[node].R)>>1;
if(l<=mid) update(node_l,l,r,value);
if(r>mid) update(node_r,l,r,value);
t[node].sum = t[node_l].sum+t[node_r].sum;
}
int query(int node,int l,int r)
{
if(t[node].L>=l&&t[node].R<=r) return t[node].sum;
pushdown(node);
int mid = (t[node].L+t[node].R)>>1;
if(r<=mid) return query(node_l,l,r);
else if(l>mid) return query(node_r,l,r);
else return query(node_l,l,mid)+query(node_r,mid+1,r);
}
}tr[25];
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>va[i];
for(int i=0;i<=22;i++)
{
tr[i].now = i;
tr[i].build(1,1,n);
}
while(m--)
{
int op,a,b,c;
cin>>op>>a>>b;
if(op==1)
{
int ans = 0;
for(int i=0;i<=22;i++)
ans += tr[i].query(1,a,b)*(1ll<<i);
cout<<ans<<"\n";
}
else
{
cin>>c;
for(int i=0;i<=22;i++)
{
if(!(c>>i&1)) continue;
tr[i].update(1,a,b,1);
}
}
}
return 0;
}
区间或代码:
int T,n,m,k;
int va[N];
int cnt[N];
struct Node{
int L,R;
int laz;
int sum;
};
struct segtree
{
int now;
Node t[4*N];
void pushdown(int node)
{
int laz = t[node].laz;
if(laz)
{
t[node_l].laz = 1;
t[node_l].sum = (t[node_l].R-t[node_l].L+1);
t[node_r].laz = 1;
t[node_r].sum = (t[node_r].R-t[node_r].L+1);
t[node].laz = 0;
}
return ;
}
void build(int node,int l,int r)
{
t[node].L = l,t[node].R = r;
if(l==r)
{
t[node].sum = (va[l]>>now&1);
return ;
}
int mid = l+r>>1;
build(node_l,l,mid);build(node_r,mid+1,r);
t[node].sum = t[node_l].sum+t[node_r].sum;
}
void update(int node,int l,int r,int value)
{
if(t[node].L>=l&&t[node].R<=r)
{
t[node].sum = (t[node].R-t[node].L+1);
t[node].laz = value;
return ;
}
pushdown(node);
int mid = (t[node].L+t[node].R)>>1;
if(l<=mid) update(node_l,l,r,value);
if(r>mid) update(node_r,l,r,value);
t[node].sum = t[node_l].sum+t[node_r].sum;
}
int query(int node,int l,int r)
{
if(t[node].L>=l&&t[node].R<=r) return t[node].sum;
pushdown(node);
int mid = (t[node].L+t[node].R)>>1;
if(r<=mid) return query(node_l,l,r);
else if(l>mid) return query(node_r,l,r);
else return query(node_l,l,mid)+query(node_r,mid+1,r);
}
}tr[25];
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>va[i];
for(int i=0;i<=22;i++)
{
tr[i].now = i;
tr[i].build(1,1,n);
}
while(m--)
{
string op;
int a,b,c;
cin>>op>>a>>b;
if(op=="SUM")
{
ll ans = 0;
for(int i=0;i<=22;i++)
ans += tr[i].query(1,a,b)*(1ll<<i);
cout<<ans<<"\n";
}
else
{
cin>>c;
for(int i=0;i<=22;i++)
{
if(!(c>>i&1)) continue;
tr[i].update(1,a,b,1);
}
}
}
return 0;
}
区间与代码:
int T,n,m,k;
int va[N];
int cnt[N];
struct Node{
int L,R;
int laz;
int sum;
};
struct segtree
{
int now;
Node t[4*N];
void pushdown(int node)
{
int laz = t[node].laz;
if(laz)
{
t[node_l].laz = 1;
t[node_l].sum = 0;
t[node_r].laz = 1;
t[node_r].sum = 0;
t[node].laz = 0;
}
return ;
}
void build(int node,int l,int r)
{
t[node].L = l,t[node].R = r;
if(l==r)
{
t[node].sum = (va[l]>>now&1);
return ;
}
int mid = l+r>>1;
build(node_l,l,mid);build(node_r,mid+1,r);
t[node].sum = t[node_l].sum+t[node_r].sum;
}
void update(int node,int l,int r,int value)
{
if(t[node].L>=l&&t[node].R<=r)
{
t[node].sum = 0;
t[node].laz = value;
return ;
}
pushdown(node);
int mid = (t[node].L+t[node].R)>>1;
if(l<=mid) update(node_l,l,r,value);
if(r>mid) update(node_r,l,r,value);
t[node].sum = t[node_l].sum+t[node_r].sum;
}
void change(int node,int x,int value)
{
if(t[node].L==x&&t[node].R==x)
{
t[node].sum = value;
return ;
}
pushdown(node);
int mid = (t[node].L+t[node].R)>>1;
if(x<=mid) change(node_l,x,value);
else change(node_r,x,value);
t[node].sum = t[node_l].sum+t[node_r].sum;
}
int query(int node,int l,int r)
{
if(t[node].L>=l&&t[node].R<=r) return t[node].sum;
pushdown(node);
int mid = (t[node].L+t[node].R)>>1;
if(r<=mid) return query(node_l,l,r);
else if(l>mid) return query(node_r,l,r);
else return query(node_l,l,mid)+query(node_r,mid+1,r);
}
}tr[32];
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>va[i];
for(int i=0;i<=30;i++)
{
tr[i].now = i;
tr[i].build(1,1,n);
}
while(m--)
{
string op;
int a,b,c;
cin>>op>>a>>b;
if(op=="AND")
{
cin>>c;
for(int i=0;i<=30;i++)
{
if((c>>i&1)) continue;
tr[i].update(1,a,b,1);
}
}
if(op=="UPD")
{
for(int i=0;i<=30;i++)
tr[i].change(1,a,(b>>i&1));
}
if(op=="QUE")
{
int ans = 0;
for(int i=0;i<=30;i++)
ans += tr[i].query(1,a,b)*(1ll<<i);
cout<<ans<<"\n";
}
}
return 0;
}
And RMQ的真正题意是求的区间最大值:
struct Node{
int L,R;
int sum;
int maxn;
}t[4*N];
int T,n,m,k;
int va[N];
void build(int node,int l,int r)
{
t[node].L = l,t[node].R = r;
if(l==r)
{
t[node].sum = va[l];
t[node].maxn = va[l];
return ;
}
int mid = l+r>>1;
build(node_l,l,mid);
build(node_r,mid+1,r);
t[node].sum = t[node_l].sum|t[node_r].sum;
t[node].maxn = max(t[node_l].maxn,t[node_r].maxn);
}
void update1(int node,int x,int value)
{
if(t[node].L>x||t[node].R<x) return ;
if(t[node].L==x&&t[node].R==x)
{
t[node].sum = value;
t[node].maxn = value;
return ;
}
update1(node_l,x,value);
update1(node_r,x,value);
t[node].sum = t[node_l].sum|t[node_r].sum;
t[node].maxn = max(t[node_l].maxn,t[node_r].maxn);
}
void update2(int node,int l,int r,int value)
{
if(t[node].L>r||t[node].R<l) return ;
if(t[node].L==t[node].R)
{
t[node].sum &= value;
t[node].maxn &= value;
return ;
}
if((value&t[node].sum)==t[node].sum) return ;
update2(node_l,l,r,value);
update2(node_r,l,r,value);
t[node].sum = t[node_l].sum|t[node_r].sum;
t[node].maxn = max(t[node_l].maxn,t[node_r].maxn);
}
int query(int node,int l,int r)
{
if(t[node].L>r||t[node].R<l) return -inf;
if(t[node].L>=l&&t[node].R<=r) return t[node].maxn;
int mid = l+r>>1;
return max(query(node_l,l,r),query(node_r,l,r));
}
signed main()
{
IOS;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>va[i];
build(1,1,n);
for(int i=1;i<=m;i++)
{
string op;
cin>>op;
if(op=="AND")
{
int a,b,c;
cin>>a>>b>>c;
update2(1,a,b,c);
}
if(op=="UPD")
{
int a,b;
cin>>a>>b;
update1(1,a,b);
}
if(op=="QUE")
{
int a,b;
cin>>a>>b;
cout<<query(1,a,b)<<"\n";
}
}
return 0;
}
总结:
多多思考。