hdu 4288 线段树 (离散化的离线算法)
输入描述:
输入第一行有一个n 表示接下来有n个命令
接下来的每一行包括一个修改命令 包括一个 字符串命令和一个整数 或者一个求和命令:
( 其意思为: add x 将x插入的数组中,del x 从数组中删除,保持数组有序,保证不插入重复的不删除不存在的
sum 命令表示输出数组中顺序%5==3 的所有元素之和 )
输出描述: 输出每一个sum命令的结果
输入样例:
9
add 1
add 2
add 3
add 4
add 5
sum
add 6
del 3
sum
输出样例:
3
4
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define MAXN 100005 struct Seg{ int lift,right; int num; long long sum[5];//存放每一段区间中顺序%5的各个值之和 void init_seg(int l,int r){ lift=l,right=r,num=0,memset(sum,0,sizeof(sum)); } } T[MAXN<<2]; char cmd[MAXN]; int x[MAXN]; int ans[MAXN]; void pushup(int i){//向上修改sum值 int t1=(i<<1)+1,t2=t1+1; for(int j=0; j<5; j++) T[i].sum[j]=T[t1].sum[j]; for(int j=T[t1].num%5,k=0; k<5; k++,j++) T[i].sum[j%5]+=T[t2].sum[k]; } void build(int i,int l,int r){ T[i].init_seg(l,r); if(l==r) return; build((i<<1)+1,l,((l+r)>>1)); build((i+1)<<1,((l+r)>>1)+1,r); } int key,add_del;//add_del==1 添加一个数 add_del==-1删除一个数 void update(int i){ if(T[i].lift==T[i].right){ T[i].num^=1; T[i].sum[0]= add_del==1 ? key : 0; return; } if(ans[(T[i].lift+T[i].right)>>1] >= key) update((i<<1)+1); else update((i+1)<<1); T[i].num+=add_del; pushup(i); } int main(){ int n,top; char ch[10]; while(~scanf("%d",&n)){ for(int i=top=0; i<n; i++){ scanf("%s",ch); cmd[i]=ch[0]; if(ch[0]!='s') scanf("%d",&x[top]),ans[top]=x[top++]; } sort(ans,ans+top); build(0,0,unique(ans,ans+top)-ans-1); for(int i=0,j=0; i<n; i++){ if(cmd[i]=='s'){ printf("%I64d\n",T[0].sum[2]); continue; } key=x[j++]; add_del= cmd[i]=='a' ? 1 : -1; update(0); } } return 0; }