CF 85D 三合一解题报告
题意:
你要维护一个集合a,每次你要支持加入一个数,删除一个数,或者求排序后
的值
链接:http://codeforces.com/contest/85/problem/D
做法一:
直接vector暴力,暴力出奇迹
vector居然有神奇的insert函数...我给跪了!
不知道set暴力能不能过...
注意要用GNU C++才能过,理由未知,MS C++会TLE
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<math.h> #include<string> #include<time.h> #include<bitset> #include<vector> #include<memory> #include<utility> #include<stdio.h> #include<sstream> #include<fstream> #include<iostream> #include<stdlib.h> #include<string.h> #include<algorithm> using namespace std; vector<int> v; int main() { #ifdef absi2011 freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif ios::sync_with_stdio(false); int n; scanf("%d",&n); int i; int flag=0; long long ans; for (i=0;i<n;i++) { static char a[105]; int x; scanf("%s",a); if (a[0]=='a') { scanf("%d",&x); v.insert(lower_bound(v.begin(),v.end(),x),x); flag=0; } if (a[0]=='d') { scanf("%d",&x); v.erase(lower_bound(v.begin(),v.end(),x)); flag=0; } if (a[0]=='s') { if (flag==1) { cout<<ans<<'\n'; continue; } ans=0; int i; for (i=2;i<v.size();i+=5) { ans+=v[i]; } cout<<ans<<'\n'; flag=1; } } return 0; }
做法二:
线段树来做
先离线
找出所有的值
然后建线段树
然后维护每个位置是否在,以及mod 5为0,1,2,3,4的值
代码:
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<string> #include<math.h> #include<time.h> #include<vector> #include<bitset> #include<memory> #include<utility> #include<fstream> #include<stdio.h> #include<sstream> #include<iostream> #include<stdlib.h> #include<string.h> #include<algorithm> using namespace std; char oper[100005]; int oper_num[100005]; int a[100005]; map<int,int> ma; long long val[1<<18][5]; int size[1<<18]; void change(int num,int l,int r,int k,int t,int x) { if (l==r-1) { val[num][0]+=x*t; size[num]+=x; return; } int mid=(l+r)/2; if (k<mid) { change(num*2+1,l,mid,k,t,x); } else { change(num*2+2,mid,r,k,t,x); } size[num]=size[num*2+1]+size[num*2+2]; int i; for (i=0;i<5;i++) { val[num][i]=val[num*2+1][i]+val[num*2+2][((i-size[num*2+1])%5+5)%5]; } } long long query(int num,int l,int r,int l0,int r0) { return val[num][2]; } int main() { #ifdef absi2011 freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif ios::sync_with_stdio(false); int n; scanf("%d",&n); int i; int t=0; for (i=0;i<n;i++) { static char opers[1005]; scanf("%s",opers); oper[i]=opers[0]; if (oper[i]!='s') { scanf("%d",&oper_num[i]); a[t++]=oper_num[i]; } } sort(a,a+t); t=unique(a,a+t)-a; for (i=0;i<t;i++) { ma[a[i]]=i; } for (i=0;i<n;i++) { if (oper[i]=='s') { cout<<query(0,0,n,0,n)<<'\n'; } else if (oper[i]=='a') { change(0,0,n,ma[oper_num[i]],oper_num[i],1); } else { change(0,0,n,ma[oper_num[i]],oper_num[i],-1); } } return 0; }
做法三:
treap直接上...
维护的和线段树差不多...
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<math.h> #include<string> #include<time.h> #include<bitset> #include<vector> #include<memory> #include<utility> #include<stdio.h> #include<sstream> #include<fstream> #include<iostream> #include<stdlib.h> #include<string.h> #include<algorithm> using namespace std; struct node { node * ch[2]; int val; int size; int weight; long long sum[5]; }; node * root; node * null; node * new_node(int val) { static node a[300005]; static int top=0; node * t=&a[top++]; t->val=val; t->weight=rand(); t->size=1; t->ch[0]=null; t->ch[1]=null; t->sum[0]=val; t->sum[1]=0; t->sum[2]=0; t->sum[3]=0; t->sum[4]=0; return t; } void update(node * &x) { int i; for (i=0;i<5;i++) { x->sum[i]=x->ch[0]->sum[i]; } int k=x->ch[0]->size; x->sum[k%5]+=x->val; k++; for (i=0;i<5;i++) { x->sum[(k+i)%5]+=x->ch[1]->sum[i]; } } void rotate(node * &x,int c) { node * y=x->ch[c]; x->ch[c]=y->ch[!c]; y->ch[!c]=x; y->size=x->size; x->size=x->ch[0]->size+x->ch[1]->size+1; update(x); update(y); x=y; } void insert_node(node * &now,node * x) { if (now==null) { now=x; return; } int c; if (x->val>now->val) { c=1; } else { c=0; } insert_node(now->ch[c],x); now->size++; update(now); if (now->ch[c]->weight>now->weight) { rotate(now,c); } } void delete_node(node * &now,int val) { now->size--; if (now->val==val) { int c; if (now->ch[0]->weight<now->ch[1]->weight) { c=1; } else { c=0; if (now->ch[0]==null) { now=null; return; } } rotate(now,c); delete_node(now->ch[!c],val); update(now); } else { if (now->val<val) { delete_node(now->ch[1],val); update(now); } else { delete_node(now->ch[0],val); update(now); } } } int main() { #ifdef absi2011 freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif int n; scanf("%d",&n); int i; null=new_node(0); null->ch[0]=null; null->ch[1]=null; null->size=0; null->weight=-1; root=null; for (i=0;i<n;i++) { static char a[1005]; scanf("%s",a); if (a[0]=='a') { int x; scanf("%d",&x); insert_node(root,new_node(x)); } else if (a[0]=='d') { int x; scanf("%d",&x); delete_node(root,x); } else { cout<<root->sum[2]<<'\n'; } } return 0; }