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

    这道题教会了我如何把一道数据结构变难,先是链,然后树,然后动态的树(' '      ) 对于此题的合并不清楚的可以先去做bzoj  2752,但是因为从线段树变成了splay,所以当节点update的时候要考虑自身的影响,对update进行分类讨论。注意翻转标记的时候有些值也会翻转。然后里面有一个细节是询问两个点是否有直接边相连,做法是将一个点a提根,然后一个点b access到根,看a在splay中是不是b的前驱

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 typedef long long ll;
      8 const ll maxn = 51000;
      9 
     10 ll n, m, a[maxn];
     11 
     12 struct node {
     13     ll data, ans, lm, rm, sum, lr, ld, size, p, key;
     14     node *son[2], *fa;
     15 }tr[maxn];
     16 
     17 void test(node* x) {
     18     if(x) {
     19         cout << x-> key <<" "<<x-> size <<" "<< x-> p <<" "<< x-> lr<< endl;
     20         //cout << x-> key <<" "<<x-> data <<" "<< x-> size <<" " << x-> ans <<" "<< x-> sum <<" "<< x-> lm <<" "<< x-> rm << endl; 
     21             for(ll i = 0; i < 2; ++ i) test(x-> son[i]);
     22     }
     23 }
     24 
     25 void update(node* x) {
     26     if(!x-> son[0] && !x-> son[1]) {
     27         x-> ans = x-> lm = x-> rm = x-> sum = x->data; x-> size = 1;
     28     }
     29     else if(x-> son[0] && !x-> son[1]) {
     30         x-> size = x-> son[0]-> size + 1; x-> sum = x-> data + x-> son[0]-> sum;
     31         x-> ans = x-> data * x-> size  + x-> son[0]-> ans + x-> son[0]-> rm;
     32         x-> lm = x-> son[0]-> lm + x-> sum;
     33         x-> rm = x-> son[0]-> rm  + x-> data * x-> size;
     34     }
     35     else if(!x-> son[0] && x-> son[1]) {
     36         x-> size = x-> son[1]-> size + 1; x-> sum = x-> data + x-> son[1]-> sum;
     37         x-> ans = x-> data * x-> size + x-> son[1]-> ans + x-> son[1]-> lm;
     38         x-> lm = x-> data * x-> size + x-> son[1]-> lm;
     39         x-> rm = x-> son[1]-> rm + x-> sum;
     40     }
     41     else {
     42         x-> size = x-> son[0]-> size + x-> son[1]-> size + 1; x-> sum = x-> data + x-> son[1]-> sum + x-> son[0]-> sum;
     43         x-> ans = x-> data * (x-> size + x-> son[0]-> size * x-> son[1]-> size) + x-> son[0]-> ans + x-> son[1]-> ans + x-> son[1]-> lm * (1 + x-> son[0]-> size) + x-> son[0]-> rm * (1 + x-> son[1]-> size);
     44         x-> lm = x-> son[0]-> lm + x-> son[0]-> sum * (x-> son[1]-> size + 1) + x-> data * (x-> son[1]-> size + 1) + x-> son[1]-> lm;
     45         x-> rm = x-> son[1]-> rm + x-> son[1]-> sum * (x-> son[0]-> size + 1) + x-> data * (x-> son[0]-> size + 1) + x-> son[0]-> rm;
     46     }
     47 }
     48 
     49 void swap(node *&a, node *&b) {
     50     node *t = a; a = b, b = t;
     51 } 
     52 
     53 void swap(int &a, int &b) {
     54     int t = a; a = b; b = t;
     55 }
     56 
     57 void pushdown(node* x) {
     58     if(!x) return;
     59     if(x-> lr) {
     60         swap(x-> son[0], x-> son[1]);
     61         for(ll i = 0; i < 2; ++ i) if(x-> son[i]) x-> son[i]-> lr ^= 1, swap(x-> son[i]-> lm, x-> son[i]-> rm);
     62         x-> lr = 0;
     63     }
     64     if(x-> ld) {
     65         for(ll i = 0; i < 2; ++ i) {
     66             if(x-> son[i]) {
     67                 x-> son[i]-> ans += x-> ld * (x-> son[i]-> size * (x-> son[i]-> size + 1) / 2) * (x-> son[i]-> size + 2) / 3;
     68                 x-> son[i]-> sum += x-> ld * x-> son[i]-> size;
     69                 x-> son[i]-> lm += x-> ld * (x-> son[i]-> size * (x-> son[i]-> size + 1) / 2);
     70                 x-> son[i]-> rm += x-> ld * (x-> son[i]-> size * (x-> son[i]-> size + 1) / 2);
     71                 x-> son[i]-> data += x-> ld; x-> son[i]-> ld += x-> ld;
     72             }
     73         }
     74         x-> ld = 0;
     75     }
     76 }
     77 
     78 void rotate(node* x, ll f) {
     79     node* t = x-> fa;
     80     if(t-> fa) {
     81         if(t-> fa-> son[0] == t) t-> fa-> son[0] = x;
     82         else t-> fa-> son[1] = x;
     83     }
     84     //x-> fa = t-> fa, x-> p = t-> p, t-> fa = x;
     85     x-> fa = t-> fa, x-> p = t-> p, x-> ans = t-> ans, x-> lm = t-> lm, x-> rm = t-> rm, x-> size = t-> size, t-> fa = x, x-> sum = t-> sum;
     86     t-> son[f] = x-> son[!f];
     87     if(x-> son[!f]) x-> son[!f]-> fa = t;
     88     x-> son[!f] = t;
     89     update(t); update(x);
     90 }
     91 
     92 void splay(node* x, node *f) {
     93     pushdown(x); 
     94     while(x-> fa != f) {
     95         pushdown(x-> fa-> fa), pushdown(x-> fa), pushdown(x);
     96         if(x-> fa-> fa == f) {
     97             ll a = x-> fa-> son[0] == x ? 0 : 1;
     98             rotate(x, a);
     99         }
    100         else {
    101             node* t = x-> fa, *r = t-> fa;
    102             ll a = r-> son[0] == t ? 0 : 1;
    103             ll b = t-> son[0] == x ? 0 : 1;
    104             if(a == b) rotate(t, a), rotate(x, b);
    105             else rotate(x, b), rotate(x, a);
    106         }
    107     }
    108 }
    109 
    110 void access(ll cur) {
    111     node* x = tr + cur; node* t; ll pp;
    112     splay(x, NULL); 
    113     if(x-> son[1]) x-> son[1]-> p = cur, x-> son[1]-> fa = NULL, x-> son[1] = NULL, update(x);
    114     while((pp = x-> p)) {
    115         t = tr + pp; splay(t, NULL);
    116         if(t-> son[1]) t-> son[1]-> p = pp, t-> son[1]-> fa = NULL, t-> son[1] = NULL, update(t); 
    117         t-> son[1] = x; x-> fa = t; update(t);
    118         splay(x, NULL);
    119     }
    120 }
    121 
    122 void reserve(ll x) {
    123     access(x); (tr + x)-> lr ^= 1; swap((tr + x)-> lm, (tr + x)-> rm);
    124 }
    125 
    126 bool query(ll a, ll b) {
    127     reserve(a);
    128     access(b);
    129     node* t = tr + a;
    130     while(t-> fa) t = t-> fa;
    131     return (t == (tr + b));
    132 }
    133 
    134 void cut(ll a, ll b) {
    135     reserve(a);
    136     access(b);
    137     node* t = (tr + b)-> son[0];
    138     if(!t) return;
    139     while(t-> son[1]) t = t-> son[1];
    140     if(t == (tr + a)) 
    141         (tr + a)-> p = 0, (tr + a)-> fa = NULL, (tr + b)-> son[0] = NULL, update(tr + b);
    142 }
    143 
    144 void link(ll a, ll b) {
    145     if(query(a, b) == 0) {
    146         (tr + a)-> p = b; 
    147     }
    148 }
    149 
    150 ll int_get() {
    151     ll x = 0; char c = (char)getchar(); bool f = 0;
    152     while(!isdigit(c) && c != '-') c = (char)getchar();
    153     if(c == '-') c = (char)getchar(), f = 1;
    154     while(isdigit(c)) {
    155         x = x * 10 + (int)(c - '0');
    156         c = (char)getchar();
    157     }
    158     return x;
    159 }
    160 
    161 struct edge {
    162     ll t; edge* next;
    163 }e[maxn * 2], *head[maxn]; ll ne = 0;
    164 
    165 void addedge(ll f, ll t) {
    166     e[ne].t = t, e[ne].next = head[f], head[f] = e + ne ++;
    167 }
    168 
    169 void dfs(ll x, ll fa) {
    170     (tr + x)-> p = fa, (tr + x)-> data = (tr + x)-> ans = (tr + x)-> lm = (tr + x)-> rm = a[x], (tr + x)-> size = 1, (tr + x)-> key = x, (tr + x)-> sum = a[x];
    171     for(edge* p = head[x]; p; p = p-> next) if(p-> t != fa) dfs(p-> t, x);
    172 }
    173 
    174 void read() {
    175     n = int_get(), m = int_get(); 
    176     for(ll i = 1; i <= n; ++ i) a[i] = int_get();
    177     for(ll i = 1; i < n; ++ i) {
    178         ll u = int_get(), v = int_get(); 
    179         addedge(u, v), addedge(v, u);
    180     }
    181     dfs(1, 0);
    182 }
    183 
    184 ll gcd(ll a, ll b) {
    185     return a % b == 0 ? b : gcd(b, a % b);
    186 }
    187 
    188 void sov() {
    189     for(int i = 1; i <= m; ++ i) {
    190         ll opt = int_get(); 
    191         if(opt == 1) {
    192             ll a, b; a = int_get(), b = int_get(); cut(a, b);
    193         }
    194         if(opt == 2) {
    195             ll a, b; a = int_get(), b = int_get(); link(a, b);
    196         }
    197         if(opt == 3) {
    198             ll a, b; a = int_get(), b = int_get();  ll d = int_get(); 
    199             if(query(a, b) == 1) {
    200                 node* t = (tr + b); 
    201                 t-> data += d;
    202                 t-> ans += (t-> size * (t-> size + 1) / 2) * (t-> size + 2) / 3 * d;
    203                 t-> lm += (t-> size * (t-> size + 1) / 2) * d;
    204                 t-> rm += (t-> size * (t-> size + 1) / 2) * d;
    205                 t-> sum += t-> size * d;
    206                 t-> ld += d;
    207             }
    208         }
    209         if(opt == 4) {
    210             ll a, b; a = int_get(), b = int_get(); 
    211             if(query(a, b) == 0) printf("-1
    ");
    212             else {
    213                 //reserve(a), access(b);
    214                 ll c = (tr + b)-> ans;
    215                 //cout << c << endl;
    216                 ll d = (tr + b)-> size * ((tr + b)-> size + 1) / 2;
    217                 ll g = gcd(c, d);
    218                 printf("%lld/%lld
    ", c / g, d / g);
    219             }
    220             //if(i == 1 || i == 24) cout << i << endl, test(tr + b), cout << endl;
    221         }
    222     }
    223     //for(ll i = 1; i <= n; ++ i) test(tr + i), cout << endl;
    224 }
    225 
    226 int main() {
    227     //freopen("test.in", "r", stdin);
    228     //freopen("test.out", "w", stdout);
    229     read(), sov();  //splay(tr + 2, NULL);
    230     //test(tr + 5);
    231     return 0;
    232 }
    View Code
  • 相关阅读:
    解决后退网页已过期或刷新询问是否重新提交表单的问题
    一行代码获取中文星期
    单例模式弹出窗体实现
    JAVA实现冒泡排序
    关于BufferedWriter.write超过30W条数据写入过慢问题。
    Ibatis的简单介绍
    链接注入(便于跨站请求伪造)(AppScan扫描结果)
    会话标识未更新(AppScan扫描结果)
    跨站点脚本编制实例(AppScan扫描结果)
    深入Java核心 Java内存分配原理精讲
  • 原文地址:https://www.cnblogs.com/ianaesthetic/p/4223696.html
Copyright © 2011-2022 走看看