hdu3276 Graph and Queries 离线+treap
之前用splay一直超时。。。这次改用treap过的也不轻松,调了一晚上。。。主要是移除操作,一个是该up的时候没up,另外一个是up的时候子结点可能不存在没判断RE了。。毕竟指针版。。。还有就是delete的时候把不该删的也删了。。。
都是比较低级的细节错误。。。
但是再让我写一遍这种题我觉得还是没问题的,这一晚上不是白浪费的。维护权值用treap果然比splay好写多了。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=2000100; const int INF=1e9+10; int n,m; int val[maxn]; struct Edge { int u,v; bool e; void read() { scanf("%d%d",&u,&v); e=1; } };Edge e[maxn]; char op[20];int x,k; struct Query { char op;int x,k; };Query q[maxn];int qn; int fa[maxn]; struct Node { Node *ch[2]; int r,v; int sz; Node() { ch[0]=ch[1]=NULL; r=rand();v=0; sz=1; } void up() { sz=1; if(ch[0]!=NULL) sz+=ch[0]->sz; if(ch[1]!=NULL) sz+=ch[1]->sz; } };Node *rt[maxn]; int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } void rot(Node* &o,int d) { Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o->up();k->up(); o=k; } void Insert(Node* &o,int x) { if(o==NULL){ o=new Node(); o->v=x; return; } int d=x<o->v?0:1; Insert(o->ch[d],x); if(o->ch[d]->r>o->r) rot(o,d^1); o->up(); } void Remove(Node* &o,int x) { if(o==NULL) return; if(o->v==x){ Node* k=o; if(o->ch[0]!=NULL&&o->ch[1]!=NULL){ int d=o->ch[0]->r>o->ch[1]->r?0:1; rot(o,d^1);Remove(o->ch[d^1],x); o->up(); } else{ Node* k=o; if(o->ch[0]==NULL) o=o->ch[1]; else o=o->ch[0]; delete k; } return; } if(x<o->v) Remove(o->ch[0],x); else Remove(o->ch[1],x); o->up(); } void JoinTo(Node* &x,Node* &y) { if(x==NULL) return; JoinTo(x->ch[0],y); JoinTo(x->ch[1],y); Insert(y,x->v); delete x;x=NULL; } int Kth(Node* &o,int k) { if(o==NULL) return 0; if(k<0||k>o->sz) return 0; int s=o->ch[1]==NULL?0:o->ch[1]->sz; if(k==s+1) return o->v; if(k<s+1) return Kth(o->ch[1],k); else return Kth(o->ch[0],k-(s+1)); } void Free(Node* &o) { if(o==NULL) return; Free(o->ch[0]); Free(o->ch[1]); delete(o); o=NULL; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif int casen=1; while(cin>>n>>m,n||m){ REP(i,1,n) rt[i]=NULL; REP(i,1,n) scanf("%d",&val[i]); REP(i,1,m) e[i].read(); qn=0; while(scanf("%s",op)&&op[0]!='E'){ if(op[0]=='D') scanf("%d",&x),e[x].e=0,q[++qn]={op[0],x,k}; else{ scanf("%d%d",&x,&k); if(op[0]=='Q') q[++qn]={op[0],x,k}; else{ q[++qn]={op[0],x,val[x]}; val[x]=k; } } } REP(i,1,n) Insert(rt[i],val[i]); REP(i,1,n) fa[i]=i; ll ans=0,cnt=0; REP(i,1,m){ if(e[i].e){ int x=find(e[i].u),y=find(e[i].v); if(x!=y){ if(rt[x]->sz>rt[y]->sz) swap(x,y); fa[x]=y,JoinTo(rt[x],rt[y]); } } } for(int i=qn;i>=1;i--){ int x=q[i].x,k=q[i].k; if(q[i].op=='D'){ int xt=find(e[x].u),yt=find(e[x].v); if(xt!=yt){ if(rt[xt]->sz>rt[yt]->sz) swap(xt,yt); fa[xt]=yt,JoinTo(rt[xt],rt[yt]); } } else if(q[i].op=='C'){ int xt=find(x); Remove(rt[xt],val[x]); Insert(rt[xt],k); val[x]=k; } else{ int xt=find(x); ans+=Kth(rt[xt],k); cnt++; } } printf("Case %d: %.6f\n",casen++,ans*1.0/cnt); REP(i,1,n) Free(rt[i]); } return 0; }
没有AC不了的题,只有不努力的ACMER!