hdu3726:Graph and Queries(treap+启发式合并+离线)

来源:互联网 发布:gamemaker 源码 编辑:程序博客网 时间:2024/05/29 04:35

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3726

题目大意:给出一幅无向边构成的图,每个点有一个点权。有3种操作:删掉一条边,更改一个点的点权,以及查询一个点所在的连通块的第k大点权。

分析:这里我们可以通过对每一个连通块维护一棵treap在log(n)的时间内完成操作2,3,至于操作1,我们发现分离比较难办,于是我们考虑离线读入,然后从后往前做,逐个合并treap。这里如果采用启发式合并,时间复杂度O(n*log^2(n))。

CODE:

#include<iostream>#include<string>#include<cstring>#include<cmath>#include<cstdio>#include<cstdlib>#include<stdio.h>#include<algorithm>#include<ctime>using namespace std;const int maxn=40010;const int maxm=120010;const int maxw=800100;const int lg=22;struct Tnode{int val,fix,Size;Tnode *lson,*rson;int Lsize() { return lson?lson->Size:0; }int Rsize() { return rson?rson->Size:0; }void Get_size() { Size=Lsize()+Rsize()+1; }} tree[maxn*lg];Tnode *Root[maxn];int fa[maxn];int cur;int u[maxm];int v[maxm];int V[maxn];bool use[maxm];struct data{int id,a,b;} work[maxw];char op[10];int n,m,w,numq;long long sum;int Case=0;Tnode *New_node(int nv){cur++;tree[cur].val=nv;tree[cur].fix=rand();tree[cur].Size=1;tree[cur].lson=tree[cur].rson=NULL;return tree+cur;}void Right_turn(Tnode *&P){Tnode *W=P->lson;P->lson=W->rson;W->rson=P;P=W;P->rson->Get_size();P->Get_size();}void Left_turn(Tnode *&P){Tnode *W=P->rson;P->rson=W->lson;W->lson=P;P=W;P->lson->Get_size();P->Get_size();}void Insert(Tnode *&P,int nv){if (!P) P=New_node(nv);else{if ( nv<P->val ){Insert(P->lson,nv);if ( P->lson->fix < P->fix ) Right_turn(P);else P->Get_size();}else{Insert(P->rson,nv);if ( P->rson->fix < P->fix ) Left_turn(P);else P->Get_size();}}}void Up(int x){if (x==fa[x]) return;Up(fa[x]);fa[x]=fa[ fa[x] ];}void Copy(Tnode *&root,Tnode *P){if (!P) return;Insert(root,P->val);Copy(root,P->lson);Copy(root,P->rson);}void Add(int x,int y){Up(x);Up(y);x=fa[x];y=fa[y];if (x==y) return;if ( Root[x]->Size < Root[y]->Size ){Copy(Root[y],Root[x]);fa[x]=y;}else{Copy(Root[x],Root[y]);fa[y]=x;}}void Delete(Tnode *&P,int nv){if ( nv==P->val ){if ( P->lson==NULL )if ( P->rson==NULL ) P=NULL;else P=P->rson;elseif ( P->rson==NULL ) P=P->lson;else{if ( P->lson->fix < P->rson->fix ){Right_turn(P);Delete(P->rson,nv);}else{Left_turn(P);Delete(P->lson,nv);}P->Get_size();}}else{if ( nv<P->val ) Delete(P->lson,nv);else Delete(P->rson,nv);P->Get_size();}}int Ask(Tnode *P,int rank){int ls=P->Lsize()+1;if (rank<ls) return Ask(P->lson,rank);if (rank>ls) return Ask(P->rson,rank-ls);return P->val;}int main(){freopen("c.in","r",stdin);freopen("c.out","w",stdout);srand( time(0) );rand(); rand();scanf("%d%d",&n,&m);while ( n || m ){Case++;cur=-1;for (int i=1; i<=n; i++){Root[i]=NULL;scanf("%d",&V[i]);fa[i]=i;}for (int i=1; i<=m; i++){use[i]=true;scanf("%d%d",&u[i],&v[i]);}numq=w=0;sum=0;scanf("%s",&op);while (op[0]!='E'){w++;if (op[0]=='D'){work[w].id=0;scanf("%d",&work[w].a);use[ work[w].a ]=false;}if (op[0]=='C'){work[w].id=1;scanf("%d",&work[w].a);work[w].b=V[ work[w].a ];scanf("%d",&V[ work[w].a ]);}if (op[0]=='Q'){work[w].id=2;scanf("%d%d",&work[w].a,&work[w].b);numq++;}scanf("%s",&op);}for (int i=1; i<=n; i++) Insert(Root[i],V[i]);for (int i=1; i<=m; i++)if (use[i]) Add(u[i],v[i]);for (int i=w; i>=1; i--){if (!work[i].id) Add(u[ work[i].a ],v[ work[i].a ]);if (work[i].id==1){int wa=work[i].a;Up(wa);Delete(Root[ fa[wa] ],V[wa]);Insert(Root[ fa[wa] ],V[wa]=work[i].b);}if (work[i].id==2){int wa=work[i].a;Up(wa);int k=Root[ fa[wa] ]->Size-work[i].b+1;if ( k<1 || k>Root[ fa[wa] ]->Size ) continue;sum+=(long long)Ask(Root[ fa[wa] ],k);}}double ans=(double)sum/(double)numq;printf("Case %d: %.6lf\n",Case,ans);scanf("%d%d",&n,&m);}return 0;}

0 0
原创粉丝点击