zoukankan      html  css  js  c++  java
  • HDU 5398 (动态树)

    Problem GCD Tree

    题目大意

      n个点的无向完全图,标号1~n,每条边u-->v 的权值为gcd(u,v),求其最大生成树,输出最大边权和。

      n<=10^5,有多个询问。  

    解题分析

      从小到大加入每个点,计算其对答案的贡献。

      对于一个点i,只有向它的约数连边才有可能对答案有贡献。

      用lct维护一棵最大生成树即可。

    参考程序

      1 #include <map>
      2 #include <set>
      3 #include <stack>
      4 #include <queue>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <string>
      8 #include <vector>
      9 #include <cstdio>
     10 #include <cstdlib>
     11 #include <cstring>
     12 #include <cassert>
     13 #include <iostream>
     14 #include <algorithm>
     15 #pragma comment(linker,"/STACK:102400000,102400000")
     16 using namespace std;
     17 
     18 #define N 400008             
     19 #define M 50008    
     20 #define LL long long
     21 #define lson l,m,rt<<1
     22 #define rson m+1,r,rt<<1|1 
     23 #define clr(x,v) memset(x,v,sizeof(x));
     24 #define bitcnt(x) __builtin_popcount(x)
     25 #define rep(x,y,z) for (int x=y;x<=z;x++)
     26 #define repd(x,y,z) for (int x=y;x>=z;x--)
     27 const int mo  = 1000000007;
     28 const int inf = 0x3f3f3f3f;
     29 const int INF = 2000000000;
     30 /**************************************************************************/ 
     31 const int maxn = 100008;
     32 vector <int> p[N];
     33 
     34 int n,m;
     35 int fa[N],val[N],mn[N],rev[N],c[N][2],st[N],ln[N],rn[N];
     36 LL ans[maxn];
     37 
     38 bool isroot(int k){
     39     return c[fa[k]][0]!=k && c[fa[k]][1]!=k;
     40 }
     41 void pushup(int x){
     42     int l=c[x][0],r=c[x][1];
     43     mn[x]=x;
     44     if  (val[mn[l]]<val[mn[x]]) mn[x]=mn[l];
     45     if  (val[mn[r]]<val[mn[x]]) mn[x]=mn[r];
     46 }
     47 void pushdown(int x){
     48     int l=c[x][0],r=c[x][1];
     49     if (rev[x]){
     50         if (l) rev[l]^=1;
     51         if (r) rev[r]^=1;
     52         rev[x]^=1;
     53         swap(c[x][0],c[x][1]);
     54     }
     55 }
     56 void rotate(int x){
     57     int y=fa[x],z=fa[y],l,r;
     58     if (c[y][0]==x) l=0; else l=1; r=l^1;
     59     if (!isroot(y)){
     60         if (c[z][0]==y) c[z][0]=x; else c[z][1]=x;
     61     }
     62     fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
     63     c[y][l]=c[x][r]; c[x][r]=y;
     64     pushup(y); pushup(x);
     65 }
     66 void splay(int x){
     67     int top=0; st[++top]=x;
     68     for (int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
     69     while (top) pushdown(st[top--]);
     70     while (!isroot(x)){
     71         int y=fa[x],z=fa[y];
     72         if (!isroot(y)){
     73             if (c[y][0]==x^c[z][0]==y) rotate(x);
     74             else rotate(y);
     75         }
     76         rotate(x);
     77     }
     78 }
     79 void access(int x){
     80     int t=0;
     81     while (x){
     82         splay(x);
     83         c[x][1]=t;
     84         pushup(x);
     85         t=x; x=fa[x];
     86     }
     87 }
     88 void rever(int x){
     89     access(x); splay(x); rev[x]^=1;
     90 }
     91 void link(int u,int v){
     92     rever(u); fa[u]=v;
     93 }
     94 void cut(int u,int v){
     95     rever(u); access(v); splay(v); fa[c[v][0]]=0; c[v][0]=0; pushup(v);
     96 }
     97 int find(int u){
     98     access(u); splay(u);
     99     while (c[u][0]) u=c[u][0];
    100     return u;
    101 }
    102 int query(int u,int v){
    103     rever(u); access(v); splay(v); return mn[v];
    104 }
    105 int main(){
    106     for (int i=1;i<=maxn;i++)
    107         for (int j=i;j<=maxn;j+=i)
    108             p[j].push_back(i);
    109     int now=0;
    110     val[0]=INF;
    111     rep(i,1,maxn){
    112         val[++now]=INF;
    113         mn[now]=now;
    114     }
    115     ans[1]=0;
    116     LL tmp=0;
    117     for (int u=1;u<=maxn;u++){
    118        for (int i=p[u].size()-2;i>=0;i--)
    119         {
    120             int v=p[u][i];
    121             int flag=1;
    122             if (find(u)==find(v)){
    123                 int t=query(u,v);
    124                 if (v>val[t]){
    125                     cut(ln[t],t);
    126                     cut(rn[t],t);
    127                     tmp-=val[t];
    128                     flag=1;
    129                 }
    130                 else flag=0;
    131             }
    132             if (flag){
    133                 mn[++now]=now; val[now]=v; ln[now]=u; rn[now]=v;
    134                 link(now,u); link(now,v);
    135                 tmp+=v;
    136             }
    137         }
    138         ans[u]=tmp;
    139     }
    140     while (~scanf("%d",&n)){
    141         printf("%lld
    ",ans[n]);
    142     }
    143 }
    View Code
  • 相关阅读:
    Asp.net MVC Web.config配置技巧
    MySQL删除表的三种方式
    MySQL中count(字段) ,count(主键 id) ,count(1)和count(*)的区别
    Centos7部署k8s集群及应用
    composer更新指定包||composer 常用命令
    LVS负载均衡策略的部署与应用
    MySQL复制表的三种方式
    Centos7部署Nginx负载均衡Tomcat服务器及session共享架构
    企业级Nginx负载均衡与keepalived高可用实战视频教程
    CentOS下用于查看系统当前登录用户信息的4种方法
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5831787.html
Copyright © 2011-2022 走看看