• 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
  • 相关阅读:
    [读书笔记]Applying UML and patterns:The agile manifesto and principles
    关于CheckBoxList和RadioButtonList的几个问题
    教你背单词
    深入剖析引用参数Ref和Out
    Web的系统测试方法 (转载)
    .net Compact Framework 程序设计起步(智能设备的程序设计)
    知道Ping的最后一个返回值TTL是什么意思吗?
    精明人的四个等级[转]
    HTTP协议下用Web Service上传大文件的解决方案
    如何解决DataGrid中删除记录后分页错误
  • 原文地址:https://www.cnblogs.com/mmlz/p/4274850.html
Copyright © 2020-2023  润新知