Treap

 

Graph and Queries

 UVALive - 5031 

第一道Treap,对着白书敲的=_=||

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 //15:15--16:00
  4 struct Node{
  5     Node *ch[2]; //左右子树
  6     int r;   //随机优先级
  7     int v;   //
  8     int s;  //节点总数
  9     Node(int v):v(v){ch[0]=ch[1]=NULL;r=rand();s=1; }
 10     bool operator <(const Node &a)const {
 11         return r<a.r;
 12     }
 13     int cmp(int x)const {
 14         if(x==v) return -1;
 15         return x<v ? 0:1;
 16     }
 17 
 18     void maintain(){
 19         s=1;
 20         if(ch[0]!=NULL) s+=ch[0]->s;
 21         if(ch[1]!=NULL) s+=ch[1]->s;
 22     }
 23 };
 24 
 25 void rotate(Node* &o,int d){   //0左旋,1右旋
 26     Node *k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
 27     o->maintain();k->maintain();o=k;
 28 }
 29 
 30 void insert(Node* &o,int x){
 31     if(o==NULL) o=new Node(x);
 32     else {
 33         int d=(x<o->v?0:1);  //不用cmp函数,因为可能有相同节点
 34         insert(o->ch[d],x);
 35         if(o->ch[d]->r>o->r) rotate(o,d^1);
 36     }
 37     o->maintain();
 38 }
 39 
 40 void remove(Node* &o,int x){
 41     int d=o->cmp(x);
 42     if(d==-1){
 43         Node* u=o;
 44         if(o->ch[0]!=NULL&&o->ch[1]!=NULL){
 45             int d2=(o->ch[0]->r>o->ch[1]->r?1:0);
 46             rotate(o,d2);remove(o->ch[d2],x);
 47         }else {
 48             if(o->ch[0]==NULL) o=o->ch[1];else o=o->ch[0];
 49             delete u;  //
 50         }
 51     }else
 52         remove(o->ch[d],x);
 53     if(o!=NULL) o->maintain();
 54 }
 55 
 56 const int maxc=500000+10;
 57 
 58 struct Command
 59 {
 60     char type;
 61     int x,p;  //根据type,p代表k或者v
 62 }command[maxc];
 63 
 64 const int maxn=20000+10;
 65 const int maxm=60000+10;
 66 
 67 int n,m,weight[maxn],from[maxm],to[maxm],removed[maxm];
 68 
 69 //并查集
 70 int pa[maxn];
 71 int gf(int x){
 72     return x==pa[x]?x:pa[x]=gf(pa[x]);
 73 }
 74 
 75 //名次树
 76 Node* root[maxn];  //Treap
 77 int kth(Node* o,int k){
 78     if(o==NULL||k<=0||k>o->s) return 0;
 79     int s=(o->ch[1]==NULL?0:o->ch[1]->s);
 80     if(k==s+1) return o->v;
 81     else if(k<=s) return kth(o->ch[1],k);
 82     else return kth(o->ch[0],k-s-1);
 83 }
 84 
 85 void mergeto(Node* &a,Node* &b){
 86     if(a->ch[0]!=NULL) mergeto(a->ch[0],b);
 87     if(a->ch[1]!=NULL) mergeto(a->ch[1],b);
 88     insert(b,a->v);
 89     delete a;
 90     a=NULL;
 91 }
 92 
 93 void removetree(Node* &x){
 94     if(x->ch[0]!=NULL)  removetree(x->ch[0]);
 95     if(x->ch[1]!=NULL)  removetree(x->ch[1]);
 96     delete x;
 97     x=NULL;
 98 }
 99 //主程序相关
100 void add_edge(int x){
101     int u=gf(from[x]),v=gf(to[x]);
102     if(u!=v){
103         if(root[u]->s<root[v]->s){
104             pa[u]=v;
105             mergeto(root[u],root[v]);
106         }else {
107             pa[v]=u;
108             mergeto(root[v],root[u]);
109         }
110     }
111 }
112 
113 int query_cnt;
114 long long query_tot;
115 void query(int x,int k){
116     query_cnt++;
117     query_tot+=kth(root[gf(x)],k);
118 }
119 
120 void change_weight(int x,int v){
121     int u=gf(x);
122     remove(root[u],weight[x]);
123     insert(root[u],v);
124     weight[x]=v;
125 }
126 
127 int main(){
128     int kase=0;
129     while(scanf("%d%d",&n,&m)==2&&n){
130         for(int i=1;i<=n;i++) scanf("%d",&weight[i]);
131         for(int i=1;i<=m;i++) scanf("%d%d",&from[i],&to[i]);
132         memset(removed,0,sizeof(removed));
133 
134         //读命令
135         int c=0;
136         for(;;){
137             char type;
138             int x,p=0,v=0;
139             scanf(" %c",&type);
140             if(type=='E') break;
141             scanf("%d",&x);
142             if(type=='D') removed[x]=1;
143             if(type=='Q') scanf("%d",&p);
144             if(type=='C'){
145                 scanf("%d",&v);
146                 p=weight[x];
147                 weight[x]=v;
148             }
149             command[c++]=(Command){type,x,p};
150         }
151 
152         //最终的图
153         for(int i=1;i<=n;i++){
154             pa[i]=i;
155             if(root[i]!=NULL) removetree(root[i]);
156             root[i]=new Node(weight[i]);
157         }
158 
159         for(int i=1;i<=m;i++) if(!removed[i]) add_edge(i);
160 
161         //反向操作
162         query_tot=query_cnt=0;
163         for(int i=c-1;i>=0;i--){
164             if(command[i].type=='D') add_edge(command[i].x);
165             if(command[i].type=='Q') query(command[i].x,command[i].p);
166             if(command[i].type=='C') change_weight(command[i].x,command[i].p);
167         }
168         printf("Case %d: %.6lf\n",++kase,query_tot/(double)query_cnt);
169     }
170     return 0;
171 }
View Code

 

posted @ 2017-07-30 16:10  yijiull  阅读(145)  评论(0编辑  收藏  举报