zoukankan      html  css  js  c++  java
  • [AtCoder Beginner Contest 133]F

    题目链接

    写完题去网上逛一圈发现全都是离线LCA,Orz。

    大致题意是一颗树上边有边权和颜色,每次询问会先把颜色为x的边的边权变为y,再询问u到v的边权和。注意,每次询问的修改只针对当前询问。

    由于题目是树上距离,所以树剖大致是可以做的。

    树剖完后将每条边的边权转点权,赋给深度较高的节点。

    每次查询,我们只要知道两点的权值和$sum1$,颜色为$x$的边的权值和$sum2$以及颜色为$x$的边的个数$num$,则答案为$sum1-sum2+num*y$。

    所以就建权值线段树,以颜色为权值,同时维护颜色个数以及这种颜色的权值和。

    就是普普通通的树剖主席树啦QAQ

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn = 3e5 + 10;
      4 typedef long long ll;
      5 struct node {
      6     int s, e, c, w, next;
      7 }edge[maxn];
      8 int head[maxn], len;
      9 int n, q;
     10 void init() {
     11     memset(head, -1, sizeof(head));
     12     len = 0;
     13 }
     14 void add(int s, int e, int c, int w) {
     15     edge[len].s = s;edge[len].e = e;
     16     edge[len].w = w;edge[len].c = c;
     17     edge[len].next = head[s];
     18     head[s] = len++;
     19 }
     20 int son[maxn], top[maxn], tid[maxn], fat[maxn], siz[maxn], dep[maxn], rak[maxn];
     21 int dfx;
     22 void dfs1(int x, int fa, int d) {
     23     siz[x] = 1, son[x] = -1, fat[x] = fa, dep[x] = d;
     24     for (int i = head[x]; i != -1; i = edge[i].next) {
     25         int y = edge[i].e;
     26         if (y == fa)
     27             continue;
     28         dfs1(y, x, d + 1);
     29         siz[x] += siz[y];
     30         if (son[x] == -1 || siz[y] > siz[son[x]])
     31             son[x] = y;
     32     }
     33 }
     34 void dfs2(int x, int c) {
     35     top[x] = c; tid[x] = ++dfx; rak[dfx] = x;
     36     if (son[x] == -1)
     37         return;
     38     dfs2(son[x], c);
     39     for (int i = head[x]; i != -1; i = edge[i].next) {
     40         int y = edge[i].e;
     41         if (y == fat[x] || y == son[x])
     42             continue;
     43         dfs2(y, y);
     44     }
     45 }
     46 int cnt, root[maxn], ls[maxn * 40], rs[maxn * 40], num[maxn * 40], val[maxn * 40];
     47 struct C {
     48     int color, dis;
     49 }a[maxn];
     50 void build(C k, int l, int r, int& i) {
     51     num[++cnt] = num[i] + 1, val[cnt] = val[i] + k.dis, ls[cnt] = ls[i], rs[cnt] = rs[i];
     52     i = cnt;
     53     if (l == r)
     54         return;
     55     int mid = l + r >> 1;
     56     if (k.color <= mid)
     57         build(k, l, mid, ls[i]);
     58     else
     59         build(k, mid + 1, r, rs[i]);
     60 }
     61 C query(int u, int v, int k, int l, int r) {
     62     if (l == r)
     63         return { num[v] - num[u],val[v] - val[u] };
     64     int mid = l + r >> 1;
     65     if (k <= mid)
     66         return query(ls[u], ls[v], k, l, mid);
     67     else
     68         return query(rs[u], rs[v], k, mid + 1, r);
     69 }
     70 int solve(int cr, int dis, int x, int y) {
     71     C ans = { 0,0 };
     72     int sum = 0;
     73     while (top[x] != top[y]) {
     74         if (dep[top[x]] < dep[top[y]])
     75             swap(x, y);
     76         C t = query(root[tid[top[x]] - 1], root[tid[x]], cr, 1, n);
     77         sum += val[root[tid[x]]] - val[root[tid[top[x]] - 1]];
     78         ans.color += t.color, ans.dis += t.dis;
     79         x = fat[top[x]];
     80     }
     81 
     82     if (x != y) {
     83         if (dep[x] < dep[y])
     84             swap(x, y);
     85         C t = query(root[tid[son[y]] - 1], root[tid[x]], cr, 1, n);
     86         sum += val[root[tid[x]]] - val[root[tid[son[y]] - 1]];
     87         ans.color += t.color, ans.dis += t.dis;
     88     }
     89     return sum - ans.dis + ans.color * dis;
     90 }
     91 int main() {
     92     scanf("%d%d", &n, &q);
     93     init();
     94     for (int i = 1, x, y, c, d; i < n; i++) {
     95         scanf("%d%d%d%d", &x, &y, &c, &d);
     96         add(x, y, c, d);
     97         add(y, x, c, d);
     98     }
     99     dfs1(1, 0, 1);
    100     dfs2(1, 1);
    101     for (int i = 0; i < len; i += 2) {
    102         int x = edge[i].e;
    103         int y = edge[i].s;
    104         if (dep[x] < dep[y])
    105             swap(x, y);
    106         a[tid[x]] = { edge[i].c, edge[i].w };
    107     }
    108     for (int i = 2; i <= dfx; i++) {
    109         root[i] = root[i - 1];
    110         build(a[i], 1, n, root[i]);
    111     }
    112     while (q--) {
    113         int x, y, u, v;
    114         scanf("%d%d%d%d", &x, &y, &u, &v);
    115         printf("%d
    ", solve(x, y, u, v));
    116     }
    117 }

  • 相关阅读:
    团队博客-会议之初
    5.2 个人作业2
    5.1 如何利用Intellij Idea搭建python编译运行环境
    4.27 python神器——Anaconda的安装与优化配置
    4.26 AlertDialog(对话框)详解
    4.25 xmapp启动mysql出现Error: MySQL shutdown unexpectedly.
    4.24 Android Studio下应用签名的方法以及获取 MD5、SHA1(签名)、SHA256 值
    4.23 2020.2新版本idea创建javaEE web文件
    4.22 Android studio 通过获取验证码用户登陆成功
    4.21 Android 记住密码和自动登录界面的实现(SharedPreferences 的用法)
  • 原文地址:https://www.cnblogs.com/sainsist/p/11557047.html
Copyright © 2011-2022 走看看