HDU-4288:Coder(线段树+离线操作)
来源:互联网 发布:windows启动盘制作 编辑:程序博客网 时间:2024/05/21 06:00
题目链接:点击打开链接
题目大意:
给你一些数让你依次添加到一个集合中,集合中的数是递增的。并且中间会求集合中下标mod5=3的数的和
解题思路:
自己完全不会做,表示线段树怎么能用来写这种东西。
后来还是给大神跪了。据说可以暴力压时间水过,不过也没尝试。
具体的思路就是先将所有数离线保存起来,然后依次再加入线段树中,具体操作也说不太清楚。
中间有一步左加右减的操作。很神奇。先将代码搬过来 t[rt].sum[i]=t[lson].sum[i]+t[rson].sum[(i-t[lson].cnt%5+5)%5]; cnt表示当前节点有效数字
可以看到当前节点 mod5=i 的值是由左节点 mod5=i 的值+右节点 mod5=x(暂且用x表示)。x=(i-t[lson].cnt%5+5)%5
这部分可能有些难以理解,举个例子说明吧 假设现在左节点有4个有效数字 ,右节点有4个有效数字。 那么他们在集合中的下标理论上是 1到8.
假设现在求 mod5=3 的值。那么左儿子就要取 下标mod5=3 的那些数,左儿子下标是正常从1开始的。但是右儿子的有效数字虽然集合中的下标是从5到8,但是在它的线段树中实际上还是1到4,那么我们当前节点mod5=3的数应该有两个 下标为3和下标为8。但是右儿子现在下标不是从5开始,所以就需要转化一下即 x=(i-t[lson].cnt%5+5)%5
下面贴代码
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <set>#include <functional>#define rank ra#define lson rt<<1#define rson rt<<1|1#define pb push_backusing namespace std;typedef long long ll;int n,m,ans;int a[100010],v[100010];char c[100010][5];struct node{ int l,r,mid; int cnt; //记录有效数字的个数 ll sum[5]; //分别mod5=i的和}t[500000];void pushup(int rt){ t[rt].cnt=t[lson].cnt+t[rson].cnt; //更新有效数字 for(int i=0;i<5;i++) //更新当前值得和 t[rt].sum[i]=t[lson].sum[i]+t[rson].sum[(i-t[lson].cnt%5+5)%5];}void build(int l,int r,int rt) //初始化{ int mid=(l+r)>>1; t[rt].l=l;t[rt].r=r; t[rt].mid=mid; for(int i=0;i<5;i++) t[rt].sum[i]=0; t[rt].cnt=0; if(l==r) return ; build(l,mid,lson); build(mid+1,r,rson);}void update(int idx,int flag,int rt){ if(t[rt].l==t[rt].r) { if(flag) //更新操作 { t[rt].sum[1]=v[idx]; t[rt].cnt=1; } if(flag<0) { t[rt].sum[1]=0; t[rt].cnt=0; } return ; } if(idx<=t[rt].mid) update(idx,flag,lson); if(idx>t[rt].mid) update(idx,flag,rson); pushup(rt);}int main(){ while(scanf("%d",&n)!=EOF) { int p=0; for(int i=1;i<=n;i++) { scanf(" %s",c[i]); if(c[i][0]!='s') { scanf("%d",&a[i]); v[++p]=a[i]; //离线储存 } } int k=1; sort(v+1,v+1+p); //排序去重 for(int i=2;i<=p;i++) { if(v[i]!=v[i-1]) v[++k]=v[i]; } build(1,k,1); for(int i=1;i<=n;i++) { if(c[i][0]=='s') cout<<t[1].sum[3]<<endl; int idx=lower_bound(v+1,v+1+k,a[i])-v; //找到大于等于它的最小的数所在位置 if(c[i][0]=='a') update(idx,1,1); if(c[i][0]=='d') update(idx,-1,1); } }}
阅读全文
0 0
- HDU-4288:Coder(线段树+离线操作)
- HDU 4288 Coder (技巧性暴力模拟+二分||线段树+离线操作)
- HDU 4288 Coder(线段树+离线处理)
- HDU 4288 Coder 离线线段树部分更新
- HDU 4288 Coder 【线段树+离线处理+离散化】
- hdu 4288 Coder (离线)
- HDU 4288 Coder(12年成都网络赛-A题-离线 + 线段树)
- HDOJ 4288 Coder (离线处理 + 线段树)
- hdu 4288 Coder (线段树)
- hdu 4288 Coder(线段树)
- hdu 4288 Coder (线段树)
- HDU 4288 Coder (线段树)
- HDU 4288 Coder(线段树)
- HDU4288 Coder(离线+线段树)
- hdu 4288(线段树) Coder
- hdu 4288 Coder (线段树)
- HDU 4288 Coder 线段树
- HDU-4288 Coder 线段树
- HDU 2837 Calculation(指数循环节)
- MySQL数据库
- 科研经验
- Hadoop(4-1)-MapReduce程序案例-统计销售商品数量
- 搜索 传染病控制 靶形数独 字串变换
- HDU-4288:Coder(线段树+离线操作)
- 搬家
- PPT中修改已插入对象的图标
- 习题 5.10 有一个分数序列2/1, 3/2, 5/3, 8/5, 13/8, 21/13, ...求出这个数列的前20项之和。
- java中equals方法和“==”的区别:
- DescriptionResourcePathLocationType Target runtime com.genuitec.runtime.generic.jee60 is not def
- 20170809 毛爷爷
- 解决Hash冲突的几种方法
- HDU 6085 Rikka with Candies 模拟bitset