• 【NOIP2018】保卫王国


    Description

    给定一棵树,求它的最小点权覆盖集,其中允许强制某个点选或不选

    Solution

    ddp用LCT维护

    明确一个关系式:最小点权覆盖集=全集-最大点权独立集

    那么n≤2000的暴力就很简单了,暴力修改,然后求最大点权独立集就好了(我在考场上就是这么写的)

    关于正解,我采用的是动态dp(动态dp的题解点这里

    根据上面的式子,我们用动态dp维护最大点权独立集,然后用全集减去就好了

    然后我们考虑强制选点的限制

    如果强制一个点选,那么我们将这个点的点权加上负无穷

    如果强制不选,那么我们将这个点的点权加上正无穷,然后全集加上正无穷就好了

    记得每次操作后要还原现场

    时间复杂度是$O(mlogn)$

    Code

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int N = 1e5 + 10;
      5 const ll INF = 1ll << 40;
      6 inline int read() {
      7     int ret = 0, op = 1;
      8     char c = getchar();
      9     while (!isdigit(c)) {
     10         if (c == '-') op = -1; 
     11         c = getchar();
     12     }
     13     while (isdigit(c)) {
     14         ret = (ret << 3) + (ret << 1) + c - '0';
     15         c = getchar();
     16     }
     17     return ret * op;
     18 }
     19 struct Edge {
     20     int nxt, to;
     21 } e[N << 1];
     22 int num, head[N];
     23 struct Matrix {
     24     ll m[2][2];
     25     Matrix() {
     26         m[0][0] = m[0][1] = m[1][0] = m[1][1] = -INF;
     27     }
     28     inline ll getans() {
     29         return max(m[0][0], m[1][0]);
     30     }
     31     inline void build(ll x, ll y) {
     32         m[0][0] = m[0][1] = x;
     33         m[1][0] = y; m[1][1] = -INF;
     34     }
     35     Matrix operator *(const Matrix &x) const {
     36         Matrix ret;
     37         for (register int i = 0; i < 2; ++i)
     38             for (register int j = 0; j < 2; ++j)
     39                 for (register int k = 0; k < 2; ++k)
     40                     ret.m[i][j] = max(ret.m[i][j], m[i][k] + x.m[k][j]);
     41         return ret;
     42     }
     43 };
     44 struct LCT {
     45     int fa, ch[2];
     46     ll f[2];
     47     Matrix x;
     48 } a[N];
     49 int n, m, val[N];
     50 ll sum;
     51 string s;
     52 inline void add(int from, int to) {
     53     e[++num].nxt = head[from];
     54     e[num].to = to;
     55     head[from] = num;
     56 }
     57 void dfs(int now, int fa) {
     58     a[now].f[1] = val[now];
     59     for (register int i = head[now]; i; i = e[i].nxt) {
     60         int to = e[i].to;
     61         if (to == fa) continue ;
     62         a[to].fa = now;
     63         dfs(to, now);
     64         a[now].f[0] += max(a[to].f[1], a[to].f[0]);
     65         a[now].f[1] += a[to].f[0];
     66     }
     67     a[now].x.build(a[now].f[0], a[now].f[1]);
     68 }
     69 inline void update(int now) {
     70     a[now].x.build(a[now].f[0], a[now].f[1]);
     71     if (a[now].ch[0]) a[now].x = a[a[now].ch[0]].x * a[now].x; 
     72     if (a[now].ch[1]) a[now].x = a[now].x * a[a[now].ch[1]].x;
     73 }    
     74 inline int isnroot(int now) {
     75     return a[a[now].fa].ch[0] == now || a[a[now].fa].ch[1] == now;
     76 }
     77 inline void rotate(int x) {
     78     int y = a[x].fa;
     79     int z = a[y].fa;
     80     int xson = a[y].ch[1] == x;
     81     int yson = a[z].ch[1] == y;
     82     int B = a[x].ch[xson ^ 1];
     83     if (isnroot(y)) a[z].ch[yson] = x;
     84     a[y].ch[xson] = B;
     85     a[x].ch[xson ^ 1] = y;
     86     if (B) a[B].fa = y;
     87     a[y].fa = x;
     88     a[x].fa = z;
     89     update(y); update(x); 
     90 }
     91 void splay(int x) {
     92     while (isnroot(x)) {
     93         int y = a[x].fa;
     94         int z = a[y].fa;
     95         if (isnroot(y)) 
     96             (a[y].ch[0] == x) ^ (a[z].ch[0] == y) ? rotate(x) : rotate(y);
     97         rotate(x); 
     98     }
     99     update(x);
    100 }
    101 void access(int x) {
    102     for (register int y = 0; x; y = x, x = a[x].fa) {
    103         splay(x);
    104         if (a[x].ch[1]) {
    105             a[x].f[0] += a[a[x].ch[1]].x.getans();
    106             a[x].f[1] += a[a[x].ch[1]].x.m[0][0];
    107         }
    108         if (y) {
    109             a[x].f[0] -= a[y].x.getans();
    110             a[x].f[1] -= a[y].x.m[0][0];            
    111         }
    112         a[x].ch[1] = y;
    113         update(x);
    114     }
    115 }
    116 void change(int x, ll y) {
    117     access(x); splay(x);
    118     a[x].f[1] += y;
    119     update(x);
    120 }
    121 void solve(int x, int op1, int y, int op2) {
    122     change(x, op1 ? -INF : INF);
    123     change(y, op2 ? -INF : INF);
    124     splay(1);
    125     sum += ((op1 ^ 1) + (op2 ^ 1)) * INF;
    126     ll ans = sum - a[1].x.getans();
    127     change(x, op1 ? INF : -INF);
    128     change(y, op2 ? INF : -INF);    
    129     sum -= ((op1 ^ 1) + (op2 ^ 1)) * INF;
    130     if (ans > INF) puts("-1");
    131     else printf("%lld
    ", ans);
    132 }
    133 int main() {
    134     n = read(); m = read(); cin >> s;
    135     for (register int i = 1; i <= n; ++i) {
    136         val[i] = read();
    137         sum += val[i];
    138     }
    139     for (register int i = 1; i < n; ++i) {
    140         int x = read(), y = read();
    141         add(x, y); add(y, x);
    142     }
    143     dfs(1, 0);
    144     while (m--) {
    145         int x = read(), op1 = read(), y = read(), op2 = read();
    146         solve(x, op1, y, op2);
    147     }
    148     return 0;
    149 }
    AC Code
  • 相关阅读:
    UE4代码片断备份
    程序到CPU的路径
    ue4 staticMesh属性记录
    UE4网络同步属性笔记
    UE4 行为树资料
    [转]浅谈B2C的数据分析
    [转载]网站分析的最基本度量(8)——Engagement
    [转载]评测流量来源(Traffic Source)的策略
    [转载]网站分析的最基本度量(7)——Impression,Click和CTR
    [转载]为什么”Bounce Rate”应该成为一个关键度量
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11367936.html
Copyright © 2020-2023  润新知