zoukankan      html  css  js  c++  java
  • hdu 3726 Graph and Queries(splay查询第k大,启发式合并,删除操作)

    题目链接: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[N];
      8 struct tree//键值可重,去重需要加num记录这个数的个数
      9 {
     10     int key,sz,f,ch[2];
     11     int add,rev;
     12 }T[N];
     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[N];
     89 //--------------------------------
     90 int n,m,g[N],w[N],nxt[N],ed,x,vis[N],f[N],qed,cas;
     91 P edge[N];
     92 
     93 struct query
     94 {
     95     char cmd[2];
     96     int x,y;
     97 }q[N];
     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
    ",++cas,ans/cnt);
    153     }
    154     return 0;
    155 }
    View Code
  • 相关阅读:
    iphone 拨打电话的 两种方法-备
    vi编辑器经典技巧 -备
    iOS图片压缩问题
    NSStirng、NSArray、以及枚举(Method小集合)
    宏定义 button 方法 --备
    debug 输出 以及宏定义--备
    从别人写的 Object-C 中 Singleton (单例) 模式 中的一些理解--备
    makefile编写---.c .cpp 混合编译makefile 模板
    图像处理之基础---线性卷积和循环卷积的区别
    图像处理之基础---卷积去噪
  • 原文地址:https://www.cnblogs.com/bin-gege/p/6293024.html
Copyright © 2011-2022 走看看