[NOIP模拟][线段树+标记下传]Query
来源:互联网 发布:怎么给手机网络加速 编辑:程序博客网 时间:2024/06/04 19:16
题目描述:
万恶的大头又出现了!他正在玩一个智障游戏:打怪兽。
现在大头的屏幕上出现了一排怪兽,每只怪兽头上有一个血条,每次大头可以选择一个区间进行攻击,攻击值为 K ,这个区间中血量小于 K 的怪兽都会被大头无情地干掉,当然怪兽不会坐以待毙,对于一个区间的怪兽,他们会在某个时刻血量同时加 X 。
大头头虽然很大,但是 IQ 并不高,在座的各位选手都不知道比他高到哪里去了。这个时候大头使出了大招——作弊器,然而大头的作弊器并不高级只能将选择的区间内血量为 7 的倍数的怪兽干掉,问:他能干掉多少怪兽?
输入格式:
第一行一个正整数 n ;
接下来 n 行 n 个整数;
再接下来一个正整数 Q ,表示操作的个数;
接下来 Q 行每行若干个整数。如果第一个数是 add ,后接 3 个正整数 a,b,X,表示在区间 [a,b] 内每个数增加 X,如果是 count,表示统计区间 [a,b] 能被 7 整除的个数。
输出格式:
对于每个询问输出一行一个答案。
样例输入:
3
2 3 4
6
count 1 3
count 1 2
add 1 3 2
count 1 3
add 1 3 3
count 1 3
样例输出:
0
0
0
1
题目分析:
线段树。懒标记+标记下传。稍微特殊的就是对于线段树tree结构体,开一个tot数组,用来存模7后不同余数的个数,修改也是修改余数值,详见代码。
附代码:
#include<iostream>#include<cstring>#include<string>#include<cstdlib>#include<cstdio>#include<ctime>#include<queue>#include<iomanip>#include<cmath>#include<cctype>#include<set>#include<map>#include<algorithm>using namespace std;const int maxn=1e5+10;int n,q,a[maxn],x,y,z;char s[10];struct node{ int tot[10];//下标代表模7的余数,存的是个数 int w; int add;}tree[4*maxn];int readint(){ char ch;int f=1,i=0; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') { ch=getchar(); f=-1; } for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0'; return i*f;}void create(int l,int r,int k){ if(l==r) { tree[k].w=a[l]%7; tree[k].tot[a[l]%7]=1; return; } int mid=(l+r)>>1; create(l,mid,k<<1); create(mid+1,r,k<<1|1); for(int i=0;i<=6;i++) tree[k].tot[i]=tree[k<<1].tot[i]+tree[k<<1|1].tot[i];}void change(int k,int v)//本题的关键操作,一个区间先已知各种余数分别的个数,修改的就是余数,而不是个数 { //如原先tot[0]=4,tot[1]=5,tot[5]=3,区间加2,则tot[2]=4,tot[3]=5,tot[0]=3 int tot[10]; for(int i=0;i<=6;i++) tot[i]=tree[k].tot[i]; for(int i=0;i<=6;i++) tree[k].tot[(i+v)%7]=tot[i];}void push_down(int k){ if(tree[k].add==0) return; tree[k<<1].add=(tree[k<<1].add+tree[k].add)%7;change(k<<1,tree[k].add); tree[k<<1|1].add=(tree[k<<1|1].add+tree[k].add)%7;change(k<<1|1,tree[k].add); tree[k].add=0;}void update(int l,int r,int k,int x,int y,int w)//修改操作,修改的是add值,即标记 { if(x<=l&&y>=r) { tree[k].add=(tree[k].add+w)%7; change(k,w); return; } int mid=(l+r)>>1; push_down(k); if(x<=mid) update(l,mid,k<<1,x,y,w); if(y>mid) update(mid+1,r,k<<1|1,x,y,w); for(int i=0;i<=6;i++) tree[k].tot[i]=tree[k<<1].tot[i]+tree[k<<1|1].tot[i];}int query(int l,int r,int k,int x,int y){ int ans=0,ans1=0,ans2=0; if(x<=l&&y>=r) return tree[k].tot[0]; int mid=(l+r)>>1; push_down(k); if(x<=mid) ans1=query(l,mid,k<<1,x,y); if(y>mid) ans2=query(mid+1,r,k<<1|1,x,y); return ans=ans1+ans2;}int main(){ //freopen("seg.in","r",stdin); //freopen("seg.out","w",stdout); n=readint(); for(int i=1;i<=n;i++) a[i]=readint(); create(1,n,1); q=readint(); while(q--) { scanf("%s",s); if(s[0]=='c') { x=readint();y=readint(); int ans=query(1,n,1,x,y); cout<<ans<<endl; } else { x=readint();y=readint();z=readint(); z=z%7; update(1,n,1,x,y,z); } } return 0;}
阅读全文
2 0
- [NOIP模拟][线段树+标记下传]Query
- NOIP模拟题 [模拟][DP][线段树]
- 【NOIP模拟】被粉碎的线段树
- EZOI NOIP模拟赛 线段树
- [NOIP模拟题][树状数组][线段树]
- 【NOIP模拟题】[状压dp][线段树]
- NOIP模拟 排列【权值线段树】
- NOIP模拟 shopping【线段树 or Splay】
- NOIP模拟 序列操作【线段树】
- Luogu 3373(线段树标记混合下传)
- 10.27NOIP 2016模拟赛 三部曲 树链剖分+线段树
- 【NOIP模拟题】【线段树】【树链剖分】发放粮食题解
- [NOIP模拟题][杂题][状压DP][DFS序][线段树]
- 【noip模拟题】[dp][二分][树链剖分][hdu5029][线段树]
- 【DFS序】【线段树】【选派士兵】【noip模拟题】
- [NOIP模拟][状压dp][dfs序列][线段树]
- 【NOIP模拟题】【线段树】2016.11.10第三题题解
- NOIP模拟题 [线段树][矩阵快速幂]
- 没有绝对安全的系统:写在AES 256破解之后
- 人工智能深渊
- java 正则表达式获取两个字符中间的字符串
- Effective Java 2.7——避免使用终结方法
- Could not read symbols解决方法
- [NOIP模拟][线段树+标记下传]Query
- node.js学习之写文件初步
- kafka 学习资料
- PHP day5 获取系统变量,html 变量输出,遍历
- springBoot整合myBatis错误:java.lang.NoSuchMethodException
- 安卓程序细节要点备忘
- MQTT协议 C#客户端
- 数据库的三大范式以及五大约束
- JS-斜杠和反斜杠的转换