zoukankan      html  css  js  c++  java
  • BZOJ3307 雨天的尾巴

    首先考虑序列怎么做。。。

    只要把操作差分了,记录在每个点上

    然后维护一棵权值线段树,表示每个颜色出现的次数,支持单点修改和查询最大值操作

    只要把序列扫一遍就好了,时间复杂度$O(n + m*logZ)$,其中$n$表述序列长度,$m$表示操作次数,$Z$表示颜色集合大小

    于是树形的时候,先树链剖分,然后把操作离线,对每一条链都扫一遍就好了,时间复杂度$O(n + m*logn*logZ)$

      1 /**************************************************************
      2     Problem: 3307
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:5120 ms
      7     Memory:86068 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <algorithm>
     12  
     13 using namespace std;
     14 const int N = 1e5 + 5;
     15 const int Z = 1e9 + 5;
     16  
     17 inline int read();
     18  
     19 struct seg {
     20     seg *ls, *rs;
     21     int mx, wmx;
     22     int tag;
     23      
     24     seg() {}
     25      
     26     #define Len (1 << 16)
     27     inline void* operator new(size_t) {
     28         static seg *mempool, *c;
     29         if (mempool == c)
     30             mempool = (c = new seg[Len]) + Len;
     31         return c++;
     32     }
     33     #undef Len
     34     inline void operator = (const seg &s) {
     35         mx = s.mx, wmx = s.wmx;
     36     }
     37      
     38     inline void update() {
     39         if (!ls && !rs) this -> mx = 0;
     40         else if (!ls || !rs) *this = (ls ? *ls : *rs);
     41         else if (ls -> mx >= rs -> mx) *this = *ls;
     42         else *this = *rs;
     43     }
     44     inline void clear() {
     45         tag = 1, mx = 0;
     46     }
     47     inline void push() {
     48         if (tag) {
     49             if (ls) ls -> clear();
     50             if (rs) rs -> clear();
     51             tag = 0;
     52         }
     53     }
     54      
     55     #define mid (l + r >> 1)
     56     void modify(int l, int r, int pos, int d) {
     57         if (l == r) {
     58             mx += d, wmx = l;
     59             return;
     60         }
     61         push();
     62         if (pos <= mid) {
     63             if (!ls) ls = new()seg;
     64             ls -> modify(l, mid, pos, d);
     65         } else {
     66             if (!rs) rs = new()seg;
     67             rs -> modify(mid + 1, r, pos, d);
     68         }
     69         update();
     70     }
     71     #undef mid
     72 } *T;
     73  
     74 struct edge {
     75     int next, to;
     76     edge(int _n = 0, int _t = 0) : next(_n), to(_t) {}
     77 } e[N << 1];
     78 int first[N], tot;
     79  
     80 struct oper {
     81     int next, z, d;
     82     oper(int _n = 0, int _z = 0, int _d = 0) : next(_n), z(_z), d(_d) {}
     83 } op[N << 6];
     84 int First[N], tot_op;
     85  
     86 struct tree_node {
     87     int fa, son, top;
     88     int sz, dep;
     89 } tr[N];
     90  
     91 int n, m;
     92 int ans[N];
     93  
     94 inline void Add_Edges(int x, int y) {
     95     e[++tot] = edge(first[x], y), first[x] = tot;
     96     e[++tot] = edge(first[y], x), first[y] = tot;
     97 }
     98  
     99 #define y e[x].to
    100 void dfs(int p) {
    101     int x;
    102     tr[p].sz = 1;
    103     for (x = first[p]; x; x = e[x].next)
    104         if (y != tr[p].fa) {
    105             tr[y].fa = p, tr[y].dep = tr[p].dep + 1;
    106             dfs(y);
    107             tr[p].sz += tr[y].sz;
    108             if (tr[tr[p].son].sz < tr[y].sz) tr[p].son = y;
    109         }
    110 }
    111  
    112 void DFS(int p) {
    113     int x;
    114     if (!tr[p].son) return;
    115     tr[tr[p].son].top = tr[p].top, DFS(tr[p].son);
    116     for (x = first[p]; x; x = e[x].next)
    117         if (y != tr[p].fa && y != tr[p].son)
    118             tr[y].top = y, DFS(y);
    119 }
    120 #undef y
    121  
    122 inline void Add_oper(int x, int y, int z) {
    123     y = tr[y].son;
    124     op[++tot_op] = oper(First[x], z, 1), First[x] = tot_op;
    125     op[++tot_op] = oper(First[y], z, -1), First[y] = tot_op;
    126 }
    127  
    128 inline void work(int x, int y, int z) {
    129     while (tr[x].top != tr[y].top) {
    130         if (tr[tr[x].top].dep < tr[tr[y].top].dep) swap(x, y);
    131         Add_oper(tr[x].top, x, z);
    132         x = tr[tr[x].top].fa;
    133     }
    134     if (tr[x].dep < tr[y].dep) swap(x, y);
    135     Add_oper(y, x, z);
    136 }
    137  
    138 void get_ans(int p) {
    139     int x;
    140     for (x = First[p]; x; x = op[x].next)
    141         T -> modify(1, Z, op[x].z, op[x].d);
    142     ans[p] = T -> mx == 0 ? 0 : T -> wmx;
    143     if (tr[p].son) get_ans(tr[p].son);
    144 }
    145  
    146 int main() {
    147     int i, x, y, z;
    148     n = read(), m = read();
    149     for (i = 1; i < n; ++i) Add_Edges(read(), read());
    150     dfs(1);
    151     tr[1].top = 1, DFS(1);
    152     for (i = 1; i <= m; ++i) {
    153         x = read(), y = read(), z = read();
    154         work(x, y, z);
    155     }
    156     T = new()seg;
    157     for (i = 1; i <= n; ++i)
    158         if (tr[i].top == i) {
    159             T -> clear();
    160             get_ans(i);
    161         }
    162     for (i = 1; i <= n; ++i)
    163         printf("%d
    ", ans[i]);
    164     return 0;
    165 }
    166  
    167 inline int read() {
    168     static int x;
    169     static char ch;
    170     x = 0, ch = getchar();
    171     while (ch < '0' || '9' < ch)
    172         ch = getchar();
    173     while ('0' <= ch && ch <= '9') {
    174         x = x * 10 + ch - '0';
    175         ch = getchar();
    176     }
    177     return x;
    178 }
    View Code

    (p.s. 窝比较懒,所以没有把颜色离散化,直接搞了动态开点线段树)

  • 相关阅读:
    nodejs初期,搭建一个登陆注册功能,(原生的)
    关于vue如何创建一个自定义组件(这是项目中经常得用的)
    关于vue 使用watch方法,详解。
    怎样用Nodejs搭建一个服务器
    关于Promise的理解及运用
    Ado.NET SQLHelper(2)
    Ado.NET SQLHelper
    MS SQLSERVER 自增ID列竟然会重复
    SQL中Left Join 与Right Join 与 Inner Join 与 Full Join的区别
    thread.start和threadstart.invoke的区别
  • 原文地址:https://www.cnblogs.com/rausen/p/4507626.html
Copyright © 2011-2022 走看看