您的位置:首页 > 产品设计 > UI/UE

hdu 3726 Graph and Queries(splay查询第k大,启发式合并,删除操作)

2017-01-17 14:39 399 查看

题目链接:hdu 3726 Graph and Queries

题意:

最开始给你n个点,每个点最开始有一个权值,并且都是独立的,现在给你m条边,表示对应的两个点是连接的。

现在有三种操作:

Q x k,表示询问与x这个点联通的所有点中第k大的权值。

D x,表示删除第x条边。

C x y,表示改变x点的权值为y。

题解:

如果正着来做肯定比较麻烦,不好维护。

一看输出,可以离线处理,那么我们就倒着搞。

把所有的询问和边,点的变化全部存起来,然后用splay来维护。

每次删除就是倒着的合并,合并采用启发式合并,多个log而已。

最后注意的是查询第k大,这里的k可能为负,这里我T了2天。- -!

1 #include<bits/stdc++.h>
2 #define F(i,a,b) for(int i=a;i<=b;++i)
3 using namespace std;
4 typedef pair<int,int>P;
5
6 const int N=2e6+7;
7 int _t,a
;
8 struct tree//键值可重,去重需要加num记录这个数的个数
9 {
10     int key,sz,f,ch[2];
11     int add,rev;
12 }T
;
13
14 struct Splay_tree
15 {
16     int root;
17     void init(){root=0;}
18     inline void nw(int &x,int key,int f)
19     {
20         T[++_t].key=key,T[_t].f=f,T[_t].sz=1;
21         T[_t].ch[0]=T[_t].ch[1]=0,x=_t;
22         T[_t].add=T[_t].rev=0;
23     }
24     inline void up(int x){T[x].sz=T[T[x].ch[0]].sz+T[T[x].ch[1]].sz+1;}
25     void rotate(int x){
26         int y=T[x].f,w=T[y].ch[1]==x;
27         T[y].ch[w]=T[x].ch[w^1];
28         if(T[x].ch[w^1])T[T[x].ch[w^1]].f=y;
29         if(T[y].f){
30             int z=T[y].f;
31             if(T[z].ch[0]==y)T[z].ch[0]=x;
32             if(T[z].ch[1]==y)T[z].ch[1]=x;
33         }
34         T[x].f=T[y].f,T[x].ch[w^1]=y,T[y].f=x;up(y);
35     }
36
37     void splay(int x,int w){
38         int s=1,i=x,y;a[1]=x;
39         while(T[x].f!=w){
40             y=T[x].f;
41             if(T[y].f!=w)(T[T[y].f].ch[0]==y)^(T[y].ch[0]==x)?rotate(x):rotate(y);
42             rotate(x);
43         }
44         if(!w)root=x;
45         up(x);
46     }
47     inline int find(int key) //返回值为key的节点 若无返回0 若有将其转移到根处
48     {
49         if(!root)return 0;
50         int x=root;
51         for(;x&&T[x].key!=key;)x=T[x].ch[T[x].key<key];
52         if(x)splay(x,0);
53         return x;
54     }
55     inline void ins(int key)//插入key键值
56     {
57         if(!root){nw(root,key,0);return;}
58         int x=root,y=0;
59         while(x)y=x,T[x].sz++,x=T[x].ch[T[x].key<key];
60         nw(T[y].ch[T[y].key<key],key,y);
61         splay(T[y].ch[T[y].key<key],0);
62     }
63     inline void det(int key)//删除值为key的节点1个
64     {
65         int x=find(key);
66         if(!x)return;
67         int y=T[x].ch[0],z=T[x].ch[1];
68         while(T[y].ch[1])y=T[y].ch[1];
69         while(T[z].ch[0])z=T[z].ch[0];
70         if(!y&&!z)root=0;
71         else if(!y)splay(z,0),T[z].ch[0]=0,up(z);
72         else if(!z)splay(y,0),T[y].ch[1]=0,up(y);
73         else splay(y,0),splay(z,y),T[z].ch[0]=0,up(z),up(y);
74     }
75     inline int kth(int k)//获得第k小的键值
76     {
77         if(k>T[root].sz||k<=0)return 0;
78         k=T[root].sz-k+1;
79         int x=root,tmp;
80         while(1)
81         {
82             tmp=T[T[x].ch[0]].sz+1;
83             if(k==tmp)break;
84             if(k<tmp)x=T[x].ch[0];else k-=tmp,x=T[x].ch[1];
85         }
86         return T[x].key;
87     }
88 }spt
;
89 //--------------------------------
90 int n,m,g
,w
,nxt
,ed,x,vis
,f
,qed,cas;
91 P edge
;
92
93 struct query
94 {
95     char cmd[2];
96     int x,y;
97 }q
;
98
99 void init(){_t=ed=0;F(i,1,n)spt[i].init(),f[i]=i,g[i]=0;}
100 void adg(int x,int c){w[++ed]=c,nxt[ed]=g[x],g[x]=ed;}
101 int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
102
103 void dfs(int r,int x)
104 {
105     if(!r)return;
106     spt[x].ins(T[r].key);
107     dfs(T[r].ch[0],x),dfs(T[r].ch[1],x);
108 }
109
110 void merge(int x,int y)
111 {
112     int fx=find(x),fy=find(y);
113     if(fx==fy)return;
114     if(T[spt[fx].root].sz<T[spt[fy].root].sz)swap(fx,fy);
115     dfs(spt[fy].root,fx),f[fy]=fx;
116 }
117
118 int main()
119 {
120     while(~scanf("%d%d",&n,&m),n+m)
121     {
122         init();
123         F(i,1,n)scanf("%d",&x),adg(i,x);
124         F(i,1,m)scanf("%d%d",&edge[i].first,&edge[i].second),vis[i]=0;
125         for(qed=0;;)
126         {
127             scanf("%s",q[++qed].cmd);
128             if(q[qed].cmd[0]=='E')break;
129             else if(q[qed].cmd[0]=='D')scanf("%d%d",&q[qed].x),vis[q[qed].x]=1;
130             else if(q[qed].cmd[0]=='Q')scanf("%d%d",&q[qed].x,&q[qed].y);
131             else scanf("%d%d",&q[qed].x,&q[qed].y),adg(q[qed].x,q[qed].y);
132         }
133         F(i,1,n)spt[i].ins(w[g[i]]);
134         F(i,1,m)if(!vis[i])merge(edge[i].first,edge[i].second);
135         double ans=0;int cnt=0;
136         for(int i=qed-1;i>0;i--)
137         {
138             if(q[i].cmd[0]=='Q')
139             {
140                 cnt++;
141                 int fx=find(q[i].x);
142                 ans+=spt[fx].kth(q[i].y);
143             }else if(q[i].cmd[0]=='D')merge(edge[q[i].x].first,edge[q[i].x].second);
144             else
145             {
146                 int fx=find(q[i].x);
147                 spt[fx].det(w[g[q[i].x]]);
148                 g[q[i].x]=nxt[g[q[i].x]];
149                 spt[fx].ins(w[g[q[i].x]]);
150             }
151         }
152         printf("Case %d: %.6f\n",++cas,ans/cnt);
153     }
154     return 0;
155 }
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: