• 可并堆/左偏树 题目泛做


    题目1 BZOJ1455 罗马游戏

    可并堆 + 并查集维护,是个可并堆的裸题。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cstdlib>
     6 #include <cctype>
     7 
     8 using namespace std;
     9 
    10 const int N = 1000000 + 5;
    11 typedef long long ll;
    12 
    13 char ss[5];
    14 int n, m, val[N], fa[N];
    15 bool sile[N];
    16 
    17 inline int read() {
    18   int x = 0;
    19   char c = getchar();
    20 
    21   while(!isdigit(c)) c = getchar();
    22   while(isdigit(c)) {
    23     x = x * 10 + c - '0';
    24     c = getchar();
    25   }
    26   return x;
    27 }
    28 
    29 struct Node {
    30   int v, dis, l, r;
    31 
    32   bool operator < (const Node &a) const {
    33     return v < a.v;
    34   }
    35 }t[N];
    36 
    37 int merge(int A, int B) {
    38   if(A == 0 || B == 0) return A + B;
    39   if(t[A].v > t[B].v) swap(A, B);
    40   t[A].r = merge(t[A].r, B);
    41   if(t[A].r) {
    42     if(t[t[A].r].dis > t[t[A].l].dis) {
    43       swap(t[A].r, t[A].l);
    44     }
    45   }
    46   t[A].dis = t[A].r ? t[t[A].r].dis + 1 : 0;
    47   return A;
    48 }
    49 
    50 int find(int x) {
    51   return fa[x] == x ? x : (fa[x] = find(fa[x]));
    52 }
    53 
    54 int main() {
    55   int x, y, fx, fy, p;
    56   
    57   n = read();
    58   for(int i = 1; i <= n; ++ i) t[i].v = read();
    59   for(int i = 1; i <= n; ++ i) fa[i] = i;
    60   m = read();
    61   for(int i = 1; i <= m; ++ i) {
    62     scanf("%s", ss);
    63     if(ss[0] == 'M') {
    64       scanf("%d%d", &x, &y);
    65       if(sile[x] || sile[y]) continue;
    66       fx = find(x); fy = find(y);
    67       if(fx != fy) {
    68         p = merge(fx, fy);
    69         fa[fx] = fa[fy] = p;
    70       }
    71     }
    72     else if(ss[0] == 'K') {
    73       scanf("%d", &x);
    74       if(sile[x]) {
    75         puts("0"); continue;
    76       }
    77       p = find(x); sile[p] = true;
    78       printf("%d
    ", t[p].v);
    79       fa[p] = merge(t[p].l, t[p].r);
    80       fa[fa[p]] = fa[p];
    81     }
    82   }
    83   return 0;
    84 }
    BZOJ

    题目2 BZOJ 4003 [JLOI2015]攻占城池

    带标记的可并堆,注意的一个问题就是在KILL完根结点之后,把没有KILL掉的点再PUSHDOWN一下。否则你会WA死的。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <cctype>
      7  
      8 using namespace std;
      9  
     10 const int N = 300000 + 5;
     11 typedef long long ll;
     12  
     13 int n, m, cnt;
     14 int fa[N], a[N], root[N], head[N];
     15 int tmp[N], city[N], c[N];
     16 int lz[N], gz[N], ans[N];
     17 ll h[N], vv[N], s[N];
     18  
     19 struct Edge {
     20   int from, to, next;
     21 }edges[N << 1];
     22  
     23 struct Node {
     24   ll v, mu, ad;
     25   int dis, l, r, id;
     26   Node() { mu = 1;}
     27   bool operator < (const Node &k) const {
     28     return v < k.v;
     29   }
     30 }t[N];
     31  
     32 void pushdown(int x) {
     33   if(!x) return;
     34  
     35   int l = t[x].l, r = t[x].r;
     36  
     37   if(t[x].mu != 1) {
     38     if(l) { t[l].v *= t[x].mu; t[l].mu *= t[x].mu; t[l].ad *= t[x].mu;}
     39     if(r) { t[r].v *= t[x].mu; t[r].mu *= t[x].mu; t[r].ad *= t[x].mu;}
     40     t[x].mu = 1;
     41   }
     42   if(t[x].ad) {
     43     if(l) { t[l].v += t[x].ad; t[l].ad += t[x].ad;}
     44     if(r) { t[r].v += t[x].ad; t[r].ad += t[x].ad;}
     45     t[x].ad = 0;
     46   }
     47   if(lz[x]) {
     48     if(l) { lz[l] += lz[x]; gz[l] += lz[x];}
     49     if(r) { lz[r] += lz[x]; gz[r] += lz[x];}
     50     lz[x] = 0;
     51   }
     52 }
     53  
     54 int merge(int s1, int s2) {
     55   if(!s1 || !s2) return s1 + s2;
     56   pushdown(s1); pushdown(s2);
     57   if(t[s1].v > t[s2].v) swap(s1, s2);
     58   t[s1].r = merge(t[s1].r, s2);
     59   if(t[s1].r)
     60     if(t[t[s1].r].dis > t[t[s1].l].dis)
     61       swap(t[s1].r, t[s1].l);
     62   t[s1].dis = t[s1].r ? t[t[s1].r].dis + 1 : 0;
     63   return s1;
     64 }
     65  
     66 void insert(int from, int to) {
     67   ++ cnt;
     68   edges[cnt].from = from;
     69   edges[cnt].to = to;
     70   edges[cnt].next = head[from];
     71   head[from] = cnt;
     72 }
     73  
     74 void dfs(int x) {
     75   for(int i = head[x]; i; i = edges[i].next) {
     76     int v = edges[i].to;
     77  
     78     if(v != fa[x]) dfs(v);
     79   }
     80   while(root[x] && t[root[x]].v < h[x]) {
     81     city[x] ++;
     82     pushdown(root[x]);
     83     ans[t[root[x]].id] = gz[root[x]];
     84     root[x] = merge(t[root[x]].l, t[root[x]].r);
     85   }
     86   if(root[x]) {
     87     if(a[x] == 0) { t[root[x]].v += vv[x]; t[root[x]].ad += vv[x];}
     88     else if(a[x] == 1) { t[root[x]].v *= vv[x]; t[root[x]].mu *= vv[x]; t[root[x]].ad *= vv[x];}
     89     lz[root[x]] ++; gz[root[x]] ++;
     90     root[fa[x]] = merge(root[fa[x]], root[x]);
     91   }
     92 }
     93  
     94 int main() {
     95   scanf("%d%d", &n, &m);
     96   for(int i = 1; i <= n; ++ i) scanf("%lld", &h[i]);
     97   a[1] = -1;
     98   for(int i = 1; i < n; ++ i) {
     99     scanf("%d%d%lld", &fa[i + 1], &a[i + 1], &vv[i + 1]);
    100     insert(i + 1, fa[i + 1]); insert(fa[i + 1], i + 1);
    101   }
    102   for(int i = 1; i <= m; ++ i) {
    103     scanf("%lld%d", &s[i], &c[i]);
    104     t[i].v = s[i]; t[i].id = i;
    105     root[c[i]] = merge(root[c[i]], i);
    106   }
    107   dfs(1);
    108   while(root[1]) {
    109     pushdown(root[1]);
    110     ans[t[root[1]].id] = gz[root[1]];
    111     root[1] = merge(t[root[1]].l, t[root[1]].r);
    112   }
    113   for(int i = 1; i <= n; ++ i) printf("%d
    ", city[i]);
    114   for(int i = 1; i <= m; ++ i) printf("%d
    ", ans[i]);
    115   return 0;
    116 }
    BZOJ 4003

    题目3 BZOJ 2809 APIO dispatching

    要注意的一个地方就是在合并堆的时候,由于我们要维护的是一个大根,所以关键字的比较要以两个节点的cost值,而我用的是v值,

    所以导致WA了许多遍。题目的思路就是DFS过程中每次把当前点与儿子们合并,然后如果sum值大于lim值就把最大的去掉。一直搞到

    最后就可以了。

     1 #include <cstdlib>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstdio>
     5 #include <cstring>
     6 #include <cctype>
     7 
     8 using namespace std;
     9 
    10 typedef long long ll;
    11 const int N = 100000 + 5;
    12 
    13 inline int read() {
    14   int x = 0;
    15   char c = getchar();
    16 
    17   while(!isdigit(c)) c = getchar();
    18   while(isdigit(c)) {
    19     x = x * 10 + c - '0';
    20     c = getchar();
    21   }
    22   return x;
    23 }
    24 
    25 int n, fa[N], head[N], master, cnt, root[N];
    26 ll cost[N], ship[N], lim, ans;
    27 
    28 struct Edge {
    29   int from, to, next;
    30 }edges[N << 1];
    31 
    32 struct Node {
    33   ll v; int l, r, sz, dis;
    34 }t[N];
    35 
    36 void insert(int u, int v) {
    37   ++ cnt;
    38   edges[cnt].from = u; edges[cnt].to = v;
    39   edges[cnt].next = head[u]; head[u] = cnt;
    40 }
    41 
    42 int merge(int a, int b) {
    43   if(!a || !b) return a + b;
    44   if(cost[a] < cost[b]) swap(a, b);
    45   t[a].r = merge(t[a].r, b);
    46   if(t[a].r)
    47     if(t[t[a].l].dis < t[t[a].r].dis)
    48       swap(t[a].r, t[a].l);
    49   t[a].dis = t[a].r ? t[t[a].r].dis + 1 : 0;
    50   return a;
    51 }
    52 
    53 void dfs(int u) {
    54   t[u].v = cost[u]; t[u].sz = 1; root[u] = u;
    55   for(int i = head[u]; i; i = edges[i].next) {
    56     int v = edges[i].to;
    57     if(v != fa[u]) {
    58       dfs(v);
    59       t[u].v += t[v].v;
    60       t[u].sz += t[v].sz;
    61       root[u] = merge(root[u], root[v]);
    62     }
    63   }
    64   while(t[u].v > lim) {
    65     t[u].v -= cost[root[u]];
    66     t[u].sz --;
    67     root[u] = merge(t[root[u]].l, t[root[u]].r);
    68   }
    69   ans = max(ans, 1LL * t[u].sz * ship[u]);
    70 }
    71 
    72 int main() {
    73   n = read(); lim = read();
    74   for(int i = 1; i <= n; ++ i) {
    75     fa[i] = read(); cost[i] = read(); ship[i] = read();
    76     insert(fa[i], i); insert(i, fa[i]);
    77     if(!fa[i]) master = i;
    78   }
    79   dfs(master);
    80   printf("%lld
    ", ans);
    81   return 0;
    82 }
    BZOJ 2809
  • 相关阅读:
    [转]数值分析——多项式插值之Lagrange插值
    [转]上拉电阻&下拉电阻&高阻态
    [转]Verilog学习笔记基本语法篇(十三)...............Gate门
    Spring MVC中的Controller是Serlvet吗?
    preparestatement和statement的区别&&简单的SQL注入
    jquery局部变量和全局变量的错误
    js 中{},[]中括号,大括号使用详解
    Java数据库学习之SQL语句动态拼接
    jquery中关键字写错导致的错误——dataType写成dateType(data写成date)
    一次隐蔽的while死循环
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5274648.html
Copyright © 2020-2023  润新知