zoukankan      html  css  js  c++  java
  • BZOJ 3091 城市旅行

    Description

    Input

    Output

    Sample Input

    4 5
    1 3 2 5
    1 2
    1 3
    2 4
    4 2 4
    1 2 4
    2 3 4
    3 1 4 1
    4 1 4

    Sample Output

    16/3
    6/1

    HINT

    对于所有数据满足 1<=N<=50,000 1<=M<=50,000 1<=Ai<=10^6 1<=D<=100 1<=U,V<=N

    Source

     维护方法我就不再赘述了,见我博客的 BZOJ 2572 高速公路。这一题和那一题的维护方法其实是一样的,但是数据结构不同,很明显这是lct嘛。

    但是那么问题就来,树上的序号id不是一定的,不像线段树一样,怎么办呢???

    这就是本题的难点——维护id。但是细细想想其实也不是很难。

    你想,他是要维护一条链上深度的id,左子树id<右子树,其实我们就是在access操作中对某一条链的id整体加上一个值或者减去一个值,这样来操作(splay维护的都是一条链)。因此,维护id就不成问题。

    但是你有没有考虑过这样一种情况:根翻转了,他所在splay的id也全部都要翻转,这怎么办?其实也不难,将其所在splay中所有id都取负,再加上splay的size+1即可。

    代码实现有许多的细节要处理:比如初始化连边,他貌似卡了你的link,如果你直接连的话,正确的做法是dfs直接将father连上去(这就是我开始tle了八九发的原因)。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 using namespace std;
      5 
      6 typedef long long ll;
      7 #define maxn 50010
      8 int n,m,ch[maxn][2],size[maxn],fa[maxn],stack[maxn];
      9 int side[maxn],next[maxn*2],toit[maxn*2],cnt;
     10 ll key[maxn],id[maxn],s1[maxn],s2[maxn],s3[maxn];
     11 ll lef[maxn],rig[maxn],sign1[maxn],sign2[maxn];
     12 bool rev[maxn];
     13 
     14 inline int getint()
     15 {
     16     int x=0,f=1;char ch=getchar();
     17     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     18     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     19     return x*f;
     20 }
     21 
     22 inline ll getlong()
     23 {
     24     ll x=0,f=1;char ch=getchar();
     25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     26     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     27     return x*f;
     28 }
     29 
     30 inline ll gcd(ll a,ll b) { return b?gcd(b,a%b):a; }
     31 
     32 inline void pushdown(int x)
     33 {
     34     int lc = ch[x][0],rc = ch[x][1];
     35     if (rev[x])
     36     {
     37         id[x] = -id[x]; s2[x] = -s2[x];
     38         swap(lef[x],rig[x]);
     39         lef[x] = -lef[x]; rig[x] = -rig[x];
     40         swap(ch[x][0],ch[x][1]);
     41         if (lc) rev[lc] ^= 1,sign2[lc] = -sign2[lc];
     42         if (rc) rev[rc] ^= 1,sign2[rc] = -sign2[rc];
     43         rev[x] = false;
     44     }
     45     if (sign2[x])
     46     {
     47         lef[x] += sign2[x]; rig[x] += sign2[x]; id[x] += sign2[x];
     48         s3[x] += (sign2[x]*s2[x]<<1)+sign2[x]*sign2[x]*s1[x];
     49         s2[x] += sign2[x]*s1[x];
     50         if (lc) sign2[lc] += sign2[x];
     51         if (rc) sign2[rc] += sign2[x];
     52         sign2[x] = 0;
     53     }
     54     if (sign1[x])
     55     {
     56         s1[x] += sign1[x]*(ll)size[x];
     57         s2[x] += (ll)size[x]*(lef[x]+rig[x])/2*sign1[x];
     58         s3[x] += (rig[x]*(rig[x]+1)*((rig[x]<<1)+1)/6-(lef[x]-1)*lef[x]*((lef[x]<<1)-1)/6)*sign1[x];
     59         key[x] += sign1[x]; 
     60         if (lc) sign1[lc] += sign1[x];
     61         if (rc) sign1[rc] += sign1[x];
     62         sign1[x] = 0;
     63     }
     64 }
     65 
     66 inline void updata(int x)
     67 {
     68     int lc = ch[x][0],rc = ch[x][1];
     69     if (lc) pushdown(lc); if (rc) pushdown(rc);
     70     size[x] = size[lc]+size[rc]+1;
     71     s1[x] = s1[lc]+s1[rc]+key[x];
     72     s2[x] = id[x]*key[x]+s2[lc]+s2[rc];
     73     s3[x] = id[x]*id[x]*key[x]+s3[lc]+s3[rc];
     74     lef[x] = rig[x] = id[x];
     75     if (lc) lef[x] = lef[lc];
     76     if (rc) rig[x] = rig[rc];
     77 }
     78 
     79 inline bool isroot(int a) { return ch[fa[a]][0] != a&&ch[fa[a]][1] != a; }
     80 
     81 inline void rotate(int x)
     82 {
     83     int y = fa[x],z = fa[y],l = ch[y][1]==x,r = l^1;
     84     if (!isroot(y)) ch[z][ch[z][1]==y] = x; fa[x] = z;
     85     if (ch[x][r]) fa[ch[x][r]] = y; ch[y][l] = ch[x][r];
     86     ch[x][r] = y; fa[y] = x;
     87     updata(y); updata(x);
     88 }
     89 
     90 inline void splay(int x)
     91 {
     92     int top = 0,i;
     93     for (i = x;!isroot(i);i = fa[i]) stack[++top] = i;
     94     stack[++top] = i;
     95     while (top) pushdown(stack[top--]);
     96     while (!isroot(x))
     97     {
     98         int y = fa[x],z = fa[y];
     99         if (!isroot(y))
    100         {
    101             if ((ch[y][0]==x)^(ch[z][0]==y)) rotate(x);
    102             else rotate(y);
    103         }
    104         rotate(x);
    105     }
    106 }
    107 
    108 inline int access(int x)
    109 {
    110     int t;
    111     for (t = 0;x;t = x,x = fa[x])
    112     {
    113         splay(x);
    114         if (ch[x][1]) sign2[ch[x][1]] -= size[ch[x][0]]+1;
    115         ch[x][1] = t; 
    116         if (t) sign2[t] += size[ch[x][0]]+1;
    117         updata(x);
    118     }
    119     return t;
    120 }
    121 
    122 inline void evert(int x)
    123 {
    124     x = access(x);  rev[x] ^= 1;
    125     sign2[x] += rev[x]*(size[x]+1);
    126 }
    127 
    128 inline int find(int x)
    129 {
    130     x = access(x);
    131     while (pushdown(x),ch[x][0]) x = ch[x][0];
    132     return x;
    133 }
    134 
    135 inline void cut(int x,int y)
    136 {
    137     evert(x); access(y); splay(y);
    138     if (ch[y][0] != x||ch[x][1] != 0) return;
    139     ch[y][0] = fa[x] = 0;
    140     updata(x);
    141     sign2[y] -= size[x];
    142 }
    143 
    144 inline void link(int x,int y)
    145 {
    146     if (find(x) == find(y)) return;
    147     evert(x); fa[x] = y;
    148 }
    149 
    150 inline void change(int x,int y,ll v)
    151 {
    152     if (find(x) != find(y)) return;
    153     evert(x); x = access(y);
    154     sign1[x] += v;
    155     pushdown(x);
    156 }
    157 
    158 inline void ask(int x,int y)
    159 {
    160     if (find(x) != find(y)) { printf("-1
    "); return; }
    161     evert(x); access(y); splay(x);
    162     ll up = -s3[x]+(ll)(size[x]+1)*s2[x],down = (ll)size[x]*(ll)(size[x]+1)>>1,d = gcd(up,down);
    163     up /= d; down /= d;
    164     printf("%lld/%lld
    ",up,down);
    165 }
    166 
    167 inline void add(int a,int b) { next[++cnt] = side[a]; side[a] = cnt; toit[cnt] = b;  }
    168 
    169 inline void ins(int a,int b) { add(a,b); add(b,a); }
    170 
    171 inline void dfs(int now,int f)
    172 {
    173     if (f) fa[now] = f;
    174     for (int i = side[now];i;i = next[i])
    175         if (toit[i] != f) dfs(toit[i],now);
    176 }
    177 
    178 int main()
    179 {
    180     freopen("3091.in","r",stdin);
    181     freopen("3091.out","w",stdout);
    182     scanf("%d %d",&n,&m);
    183     for (int i = 1;i <= n;++i)
    184     {
    185         key[i] = getlong();
    186         s1[i] = s2[i] = s3[i] = key[i];
    187         size[i] = lef[i] = rig[i] = id[i] = 1;
    188     }
    189     for (int i = 1;i < n;++i)
    190     {
    191         int a = getint(),b = getint();
    192         ins(a,b);
    193     }
    194     dfs(1,0);
    195     while (m--)
    196     {
    197         int opt = getint();
    198         if (opt == 3)
    199         {
    200             int u = getint(),v = getint(); ll d = getlong();
    201             change(u,v,d);
    202         }
    203         else
    204         {
    205             int u = getint(),v = getint();
    206             if (opt == 1) cut(u,v);
    207             else if (opt == 2) link(u,v);
    208             else ask(u,v);
    209         }
    210     }
    211     fclose(stdin); fclose(stdout);
    212     return 0;
    213 }
    View Code
  • 相关阅读:
    SD卡测试
    测试人员可能会遇到的问题
    HDU 1024 Max Sum Plus Plus
    HDU 1176 免费馅饼
    HDU 1257 最少拦截系统
    HDU 1087 Super Jumping! Jumping! Jumping!
    poj 1328 Radar Installation
    poj 1753 Flip Game
    HDU 1003 Max Sum
    HDU 5592 ZYB's Premutation(BestCoder Round #65 C)
  • 原文地址:https://www.cnblogs.com/mmlz/p/4274850.html
Copyright © 2011-2022 走看看