HDU 4288 Coder 线段树

来源:互联网 发布:javascript join方法 编辑:程序博客网 时间:2024/06/04 18:26

求下标i%5==3的和,首先用离散化处理一下,比如1,10,100这3个数,由于题目只要求大小顺序,所以可以看成1,2,3,这就是离散化。

然后用线段树记录该段个数num和下标i%5相同的和sum[i%5]。维护num和sum[ ]即可。

由于题目说:where the set S is written as {a1, a2, ... , ak} satisfying a1 < a2 < a3 < ... < ak  ,所以remark处肯定是sum[rt][1]

原来我怕出错,都用LL 跑了1300ms+过了,题目不是限时1000的么- -!非sum改成int只跑了800ms+。

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int N=1e5+5;typedef long long LL;int num[N*4];LL sum[N*4][5];//树 第i个sum和int d[N],cnt,nn;//离散化数组dstruct oper{int op,val;//1-add,2-del,3-sum}op[N];void input(int i){char str[10];scanf("%s",str);if(str[0]=='a'){op[i].op=1;scanf("%d",&op[i].val);d[cnt++]=op[i].val;}else if(str[0]=='d'){op[i].op=2;scanf("%d",&op[i].val);}elseop[i].op=3;}void build(int l,int r,int rt){num[rt]=0;for(int i=0;i<5;i++)sum[rt][i]=0;if(l==r) return;int m=(l+r)/2;build(lson);build(rson);}void push_up(int rt){num[rt]=num[rt*2]+num[rt*2+1];for(int i=0;i<5;i++){int right=(i+5-num[rt*2]%5)%5;sum[rt][i]=sum[rt*2][i]+sum[rt*2+1][right];}}void update(int p,int c,LL val,int l,int r,int rt){//单点更新if(l==r){        num[rt]+=c;        sum[rt][1]+=val;// -- remark --        return;}int m=(l+r)/2;if(p<=m)update(p,c,val,lson);if(p>m)update(p,c,val,rson);push_up(rt);}int main(){int n;while(~scanf("%d",&n)){cnt=0;for(int i=0;i<n;i++)input(i);sort(d,d+cnt);nn=unique(d,d+cnt)-d;//离散化build(1,nn,1);for(int i=0;i<n;i++){if(op[i].op==1){int loc=lower_bound(d,d+nn,op[i].val)-d;update(loc+1,1,op[i].val,1,nn,1);}else if(op[i].op==2){int loc=lower_bound(d,d+nn,op[i].val)-d;update(loc+1,-1,-op[i].val,1,nn,1);}elseprintf("%I64d\n",sum[1][3]);}}return 0;}


0 0
原创粉丝点击