zoukankan      html  css  js  c++  java
  • LA 5031 图询问

    题目链接:https://vjudge.net/contest/159527#problem/A

    题意:(求一个 图 中的连通分量中的 第 k 大)

    一张图,n 个点,m 条边,

    有一些操作:

    删除 ID 为 x 的边,(从 1 到 m);

    询问 x 所在的连通分量 里面第 k 大的权值;

    把结点 X 的权值 改成 V;

    求:

    所有的询问后,计算平均值;

    每个连通分量都是一颗Treap树,加边操作,就是树的合并;

    刘汝佳采用的是离线算法,我还是第一次听说,但是还是可以按照题意直接模拟的(我猜,但是很麻烦);因为在Treap中删边不同于删点;

    什么是离线算法呢?

    把操作顺序反过来处理,执行完所有 删除边操作,然后建Treap,要是不在同一个连通分量里面(并查集判断),这就涉及到递归合并Treap树了,这里采用了启发式合并;

    然后反向操作,遇到 D,就是加边(加边操作同上),

    询问,就是在 X 所在连通分量里面,寻找第 k 大;

    改权,就是删除这个点,然后从新加点;

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 struct Node
      6 {
      7     Node *ch[2];
      8     int r;  //优先级
      9     int v;  //
     10     int s;  //结点总数
     11 
     12     Node(int v):v(v)
     13     {
     14         ch[0] = ch[1] = NULL;
     15         r = rand();
     16         s = 1;
     17     }
     18 
     19     bool operator < (const Node& rhs) const
     20     {
     21         return r < rhs.r;
     22     }
     23 
     24     int cmp(int x) const
     25     {
     26         if(x==v) return -1;
     27         return x < v ? 0 : 1;
     28     }
     29 
     30     void maintain()
     31     {
     32         s = 1;
     33         if(ch[0]!=NULL) s+=ch[0]->s;
     34         if(ch[1]!=NULL) s+=ch[1]->s;
     35     }
     36 
     37 
     38 };
     39 
     40 void rotate(Node* &o,int d)
     41 {
     42     Node* k = o->ch[d^1];
     43     o->ch[d^1] = k ->ch[d];
     44     k->ch[d] = o;
     45     o->maintain();
     46     k->maintain();
     47     o = k;
     48 }
     49 
     50 void insert(Node* &o,int x)
     51 {
     52     if(o==NULL) o = new Node(x);
     53     else
     54     {
     55         int d = (x < o->v? 0 : 1);
     56         insert(o->ch[d],x);
     57         if(o->ch[d]->r > o->r)
     58             rotate(o,d^1);
     59     }
     60     o->maintain();
     61 }
     62 
     63 void remove(Node* &o,int x)
     64 {
     65     int d = o->cmp(x);
     66     if(d==-1)
     67     {
     68         Node* u = 0;
     69         if(o->ch[0]!=NULL&&o->ch[1]!=NULL)
     70         {
     71             int d2 = (o->ch[0]->r > o->ch[1]->r ? 1 : 0);
     72             rotate(o,d2);
     73             remove(o->ch[d2],x);
     74         }
     75         else
     76         {
     77             if(o->ch[0]==NULL)
     78                 o = o->ch[1];
     79             else o = o->ch[0];
     80         }
     81     }
     82     else
     83         remove(o->ch[d],x);
     84 
     85     if(o!=NULL) o->maintain();
     86 }
     87 
     88 
     89 const int maxc = 500000 + 10;
     90 struct Command
     91 {
     92     char type;
     93     int x,p;
     94 } commands[maxc];
     95 
     96 const int maxn = 20000 + 10;
     97 const int maxm = 60000 + 10;
     98 int n,m;
     99 int weight[maxn],from[maxm],to[maxm],removed[maxm];
    100 
    101 
    102 int pa[maxn];
    103 int findset(int x)
    104 {
    105     return pa[x]!=x ? pa[x] = findset(pa[x]):x;
    106 }
    107 
    108 Node* root[maxn];   //Treap
    109 
    110 int kth(Node* o,int k)
    111 {
    112     if(o==NULL||k<=0||k> o->s) return 0;
    113     int s = (o->ch[1]==NULL?0:o->ch[1]->s);
    114     if(k==s+1) return o->v;
    115     else if(k<=s) return kth(o->ch[1],k);
    116     else return kth(o->ch[0],k-s-1);
    117 }
    118 
    119 void mergeto(Node* &src,Node* &dest)
    120 {
    121     if(src->ch[0]!=NULL) mergeto(src->ch[0],dest);
    122     if(src->ch[1]!=NULL) mergeto(src->ch[1],dest);
    123     insert(dest,src->v);
    124     delete src;
    125     src = NULL;
    126 }
    127 
    128 void removetree(Node* &x)
    129 {
    130     if(x->ch[0]!=NULL) removetree(x->ch[0]);
    131     if(x->ch[1]!=NULL) removetree(x->ch[1]);
    132     delete x;
    133     x = NULL;
    134 }
    135 
    136 void add_edge(int x)
    137 {
    138     int u = findset(from[x]),v=findset(to[x]);
    139     if(u!=v)
    140     {
    141         if(root[u]->s < root[v]->s)
    142         {
    143             pa[u] = v;
    144             mergeto(root[u],root[v]);
    145         }
    146         else
    147         {
    148             pa[v] = u;
    149             mergeto(root[v],root[u]);
    150         }
    151     }
    152 }
    153 
    154 int query_cnt;
    155 long long query_tot;
    156 void query(int x,int k)
    157 {
    158     query_cnt++;
    159     query_tot +=kth(root[findset(x)],k);
    160 }
    161 
    162 void change_weight(int x,int v)
    163 {
    164     int u = findset(x);
    165     remove(root[u],weight[x]);
    166     insert(root[u],v);
    167     weight[x] = v;
    168 }
    169 
    170 
    171 int main()
    172 {
    173     int kase = 0;
    174     while(scanf("%d%d",&n,&m)==2&&n)
    175     {
    176         for(int i=1; i<=n; i++)
    177             scanf("%d",&weight[i]);
    178         for(int i=1; i<=m; i++)
    179             scanf("%d%d",&from[i],&to[i]);
    180         memset(removed,0,sizeof(removed));
    181 
    182         int c = 0;
    183         for(;;)
    184         {
    185             char type;
    186             int x,p=0,v = 0;
    187             scanf(" %c",&type);
    188             if(type=='E') break;
    189             scanf("%d",&x);
    190             if(type=='D') removed[x]= 1;    //删掉的边
    191             if(type=='Q') scanf("%d",&p);
    192             if(type=='C')
    193             {
    194                 scanf("%d",&v);
    195                 p = weight[x];
    196                 weight[x] = v;
    197             }
    198             commands[c++] = (Command)
    199             {
    200                 type,x,p
    201             };
    202         }
    203 
    204         //最终的图
    205         for(int i=1; i<=n; i++)
    206         {
    207             pa[i] = i;
    208             if(root[i]!=NULL) removetree(root[i]);
    209             root[i] = new Node(weight[i]);
    210         }
    211         for(int i=1; i<=m; i++)
    212         {
    213             if(!removed[i]) //id为i这条边没有被删掉
    214                 add_edge(i);
    215         }
    216 
    217         query_cnt = query_tot = 0;
    218         for(int i=c-1; i>=0; i--)
    219         {
    220             if(commands[i].type=='D') add_edge(commands[i].x);  //加上边
    221             if(commands[i].type=='Q') query(commands[i].x,commands[i].p);//第p大
    222             if(commands[i].type=='C') change_weight(commands[i].x,commands[i].p);
    223         }
    224 
    225         printf("Case %d: %.6lf
    ",++kase,query_tot/(double)query_cnt);
    226 
    227     }
    228 
    229 
    230 
    231     return 0;
    232 }
    View Code
  • 相关阅读:
    第2课 检索数据
    jmeter断言-响应断言
    jmeter参数化
    性能测试重要指标
    Web测试中,各类web控件测试点(转)
    jmeter-分布式集群测试-执行机无响应数据
    jmeter分布式集群测试-Error initialising remote server
    jmeter分布式集群测试-修改执行机默认端口
    jmeter分布式集群测试
    selenium-webdriver层级定位元素
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6735840.html
Copyright © 2011-2022 走看看