Wannafly模拟赛4 CSum(线段树)
来源:互联网 发布:hao123网络连接错误 编辑:程序博客网 时间:2024/06/05 19:26
题目描述
考虑维护一个这样的问题:
(1) 给出一个数组A,标号为1~n
(2) 修改数组中的一个位置。
(3) 询问区间[l,r]中所有子集的位运算and之和mod(109+7)。
位运算and即为“pascal中的and”和“C/C++中的&”
我们定义集合S={ l , l+1 , ... , r-1 , r}
若集合T,T ∩ S = T,则称T为S的子集
设f(T)=AT1 and AT2 and ... and ATk (设k为T集大小,若k=0则f(T)=0)
所有子集的位运算and之和即为∑f(T)
那么,现在问题来了。
(1) 给出一个数组A,标号为1~n
(2) 修改数组中的一个位置。
(3) 询问区间[l,r]中所有子集的位运算and之和mod(109+7)。
位运算and即为“pascal中的and”和“C/C++中的&”
我们定义集合S={ l , l+1 , ... , r-1 , r}
若集合T,T ∩ S = T,则称T为S的子集
设f(T)=AT1 and AT2 and ... and ATk (设k为T集大小,若k=0则f(T)=0)
所有子集的位运算and之和即为∑f(T)
那么,现在问题来了。
输入描述:
第一行,一个正整数N第二行,N个非负整数,为数组A第三行,一个正整数M,为操作次数接下来M行格式如下修改操作: 1 x y,将Ax修改为y询问操作: 2 l r,区间[l,r]中所有子集的位运算and之和 mod(109+7)
输出描述:
对于每次询问输出一行,为该次询问的答案mod(109+7)。long long 请使用lld
示例1
输入
31 2 362 1 31 1 22 1 32 2 31 2 52 1 3
输出
915713
说明
第一次询问:Answer =1+2+3+(1 and 2)+(1 and 3)+(2 and 3)+(1 and 2 and 3)=1+2+3+0+1+2+0=9第二次询问:Answer =2+2+3+(2 and 2)+(2 and 3)+(2 and 3)+(2 and 2 and 3)=2+2+3+2+2+2+2=15第三次询问:Answer =2+3+(2 and 3)=2+3+2=7第四次询问:Answer =2+5+3+(2 and 5)+(2 and 3)+(3 and 5)+(2 and 5 and 3)=2+5+3+0+2+1+0=13
备注:
M,N≤105,Ai≤109
这题很考验思维;
一看到问一个区间中的子集就蒙了,其实仔细想一想就知道&运算只要有一个0,这个子集这个位的贡献就是0,所以只要统计,一段区间中这个位的1的个数就可以了
#include <cstdio>#include <cstring>#include <algorithm>#include <bits/stdc++.h>using namespace std;const int N = 2e5+10;typedef long long LL;const LL mod = 1e9+7;struct node{ int a[35];} p[N<<2];void build(int l,int r,int rt){ if(l==r) { LL x; scanf("%lld", &x); for(int i=0; i<32; i++,x/=2) { int v=x%2; p[rt].a[i]=v; } return ; } int mid=(l+r)/2; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); for(int i=0; i<=32; i++) p[rt].a[i]=p[rt<<1].a[i]+p[rt<<1|1].a[i]; return ;}void update(int pos,int v,int l,int r,int rt){ if(l==r) { for(int i=0; i<=32; i++,v/=2) { int x=v%2; p[rt].a[i]=x; } return ; } int mid=(l+r)/2; if(pos<=mid) update(pos,v,l,mid,rt<<1); else update(pos,v,mid+1,r,rt<<1|1); for(int i=0; i<=32; i++) p[rt].a[i]=p[rt<<1].a[i]+p[rt<<1|1].a[i]; return ;}node query(int L,int R,int l,int r,int rt){ if(l>=L&&r<=R) return p[rt]; int mid=(l+r)/2; node p1,p2,p3; memset(p1.a,0,sizeof(p1.a)); memset(p2.a,0,sizeof(p2.a)); if(L<=mid) p1=query(L,R,l,mid,rt<<1); if(R>mid) p2=query(L,R,mid+1,r,rt<<1|1); for(int i=0;i<=32;i++) p3.a[i]=p1.a[i]+p2.a[i]; return p3;}LL b[N];int main(){ b[0]=1; for(int i=1;i<=110000;i++) b[i]=b[i-1]*2%mod; int n; scanf("%d", &n); build(1,n,1); int q; scanf("%d", &q); while(q--) { int x, l, r; scanf("%d %d %d", &x, &l, &r); if(x==1) update(l,r,1,n,1); else { node res=query(l,r,1,n,1); LL ans=0; for(LL i=0;i<=32;i++) ans=(ans+b[i]*(b[res.a[i]]-1)%mod)%mod; cout<<ans<<endl; } } return 0;}
阅读全文
0 0
- Wannafly模拟赛4 CSum(线段树)
- Wannafly模拟赛3 监视任务(贪心+线段树)
- Wannafly模拟赛4
- Wannafly模拟赛3-F 监视任务(贪心+线段树区间更新)
- Wannafly模拟赛 树(dp)
- Wannafly模拟赛4 题解
- Wannafly模拟赛4 A Laptop (RMQ)
- Wannafly模拟赛4 C Sum(树状数组)
- Wannafly模拟赛4 A Laptop (前缀数组)
- Wannafly模拟赛4:A-Laptop(后缀)
- Wannafly模拟赛4 D Fancy Signal Translate(字典树)
- Wannafly模拟赛4 B Distance
- Wannafly模拟赛4 B Distance
- Wannafly模拟赛4 B题
- Nowcode Sum(Wannafly模拟赛4)
- Wannafly模拟赛 树【思维+Dp】
- 10.9wannafly模拟赛
- Wannafly模拟赛3
- 例题7-12 旋转游戏(The Rotation Game, Shanghai 2004, UVa1343)
- Java实现传教士与野人过河问题
- p43-3.1(1)
- Python学习笔记:七 银行管理系统
- Google C++命名规范
- Wannafly模拟赛4 CSum(线段树)
- JS五种运算符,运算符的优先级
- java 函数参数的传递方式说明(string、 引用类型、基本类型)
- volley的使用
- C#装箱和拆箱
- Leetcode 330. Patching Array
- struts2 做分页
- B. Maximum of Maximums of Minimums --codeforces
- BZOJ4350: 括号序列再战猪猪侠(区间DP)