zoukankan      html  css  js  c++  java
  • [luogu4556][Vani有约会]

    题目链接

    吐槽

    这道题调了7个小时也是够了。最后只好比着题解做了一遍2333

    思路

    首先考虑n=2000的情况。因为这是在一条路径上,所以可以考虑差分。用a[i][j]表示第i个点中j这种粮食出现的次数。加入要在从x到y的路径上加入c这种粮食。将这条路径分为两部分进行差分。从x到lca,也就是将a[x][c]++,a[fa[lca]]--。从y到son[lca]。就是将a[y][c]++,a[lca]--。(详细原因见树上差分)最后dfs一遍,并且在回溯的时候合并一下就行了。
    那么对于n=100000的数据,只要用线段树合并优化一下就行了。也就是将a数组改为n棵动态开点线段树。合并的时候用线段树合并的板子合并一下就行了。

    代码

    /*
    * @Author: wxyww
    * @Date:   2018-12-10 14:37:11
    * @Last Modified time: 2018-12-10 21:15:06
    */
    #include<cstdio>
    #include<iostream>
    #include<vector>
    using namespace std;
    typedef long long ll;
    #define Ls TR[cur].ls
    #define Rs TR[cur].rs
    ll read() {
       ll x = 0,f = 1;char c = getchar();
       while(c < '0' || c > '9') {
          if(c == '-') f = -1;
          c = getchar();
       }
       while(c >= '0' && c <= '9') {
          x = x * 10 + c - '0';
          c = getchar();
       }
       return x * f;
    }
    const int N = 100000 + 100,logN = 20;
    struct node {
       int ls,rs,ans,sum;
    }TR[N * 50];
    int n,m,dep[N],lca[N][logN + 30],root[N];
    vector<int>e[N];
    int num;
    void get_lca(int u,int father) {
       for(int i = 1;i < logN;++i) lca[u][i] = lca[lca[u][i - 1]][i - 1];
       int k = e[u].size();
       for(int i = 0;i < k;++i) {
          int v = e[u][i];
          if(v == father) continue;
          lca[v][0] = u;
          dep[v] = dep[u] + 1;
          get_lca(v,u);
       }
    }
    int LCA(int x,int y) {
       if(dep[x] < dep[y]) swap(x,y);
       for(int i = logN - 1;i >= 0;--i)
          if(dep[lca[x][i]] >= dep[y]) x = lca[x][i];
       if(x == y) return y;
       for(int i = logN - 1;i >= 0;--i) {
          if(lca[x][i] != lca[y][i]) {
             x = lca[x][i];y = lca[y][i];
          }
       }
       return lca[x][0];
    }
    void up(int cur) {
       if(TR[Ls].sum >= TR[Rs].sum) {
          TR[cur].sum = TR[Ls].sum;
          TR[cur].ans = TR[Ls].ans;
       }
       else {
          TR[cur].sum = TR[Rs].sum;
          TR[cur].ans = TR[Rs].ans;
       }
    }
    void update(int &cur,int l,int r,int pos,int c) {
       if(!cur) cur = ++num;
       if(l == r) {
          TR[cur].sum += c;
          TR[cur].ans = l;
          return;
       }
       int mid = (l + r) >> 1;
       if(pos <= mid) update(Ls,l,mid,pos,c);
       else update(Rs,mid + 1,r,pos,c);
       up(cur);
    }
    int merge(int cur,int a,int l,int r) {
       if(!cur) return a;
       if(!a) return cur;
       if(l == r) {
          TR[cur].sum += TR[a].sum;
          TR[cur].ans = l;
          return cur;
       }
       int mid = (l + r) >> 1;
       Ls = merge(Ls,TR[a].ls,l,mid);
       Rs = merge(Rs,TR[a].rs,mid + 1,r);
       up(cur);
       return cur;
    }
    void dfs(int u,int father) {
       int k = e[u].size();
       for(int i = 0;i < k;++i) {
          int v = e[u][i];
          if(v == father) continue;
          dfs(v,u);
          merge(root[u],root[v],1,N - 100);
       }
    }
    int main() {
       int n = read(),m = read();
       for(int i = 1;i < n;++i) {
          int x = read(),y = read();
          e[x].push_back(y);
          e[y].push_back(x);
       }
       dep[1] = 1;
       for(int i = 1;i <= n;++i) root[i] = ++num;
       get_lca(1,0);
       while(m--) {
          int x = read(),y = read(),c = read();
          int K = LCA(x,y);
          update(root[x],1,N - 100,c,1);
          update(root[y],1,N - 100,c,1);
          update(root[K],1,N - 100,c,-1);
          if(lca[K][0]) update(root[lca[K][0]],1,N - 100,c,-1);
       }
       dfs(1,0);
       for(int i = 1;i <= n;++i) {
          if(TR[root[i]].sum == 0) puts("0");
          else
          printf("%d
    ",TR[root[i]].ans);
       }
    
       return 0;
    }
    
  • 相关阅读:
    Logstash收集Tomcat日志
    Logstash收集日志
    ELK搭建&Logstash 日志收集
    ELK介绍
    中文分词器
    ES数据备份与恢复
    Python开发之路
    Linux阅读目录
    333
    22222222
  • 原文地址:https://www.cnblogs.com/wxyww/p/10099318.html
Copyright © 2011-2022 走看看