2019年ICPC南昌网络赛 J. Distance on the tree 树链剖分+主席树

边权转点权,每次遍历到下一个点,把走个这条边的权值加入主席树中即可。

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxx = 2e5+10;
struct node{
  int l,r,cnt;
}tree[maxx*40];
int head[maxx],rk[maxx],siz[maxx],top[maxx],son[maxx],d[maxx],fa[maxx],id[maxx],rt[maxx];
int dis[maxx];
struct Edge{
  int Next,to,w;
}edge[maxx<<1];
int root[maxx];
int tot=0,cnt=0,order;
void inserts(int l,int r,int pre,int &now,int pos){
    now=++cnt;
    tree[now]=tree[pre];
    tree[now].cnt++;
    if (l==r){
        return ;
    }
    int mid=(l+r)>>1;
    if (pos<=mid){
        inserts(l,mid,tree[pre].l,tree[now].l,pos);
    }else {
        inserts(mid+1,r,tree[pre].r,tree[now].r,pos);
    }
}
int query(int L,int R,int l,int r,int w){
    if (l==r){
        return tree[R].cnt-tree[L].cnt;
    }
    int mid=(l+r)>>1;
    if (w<=mid){
        return query(tree[L].l,tree[R].l,l,mid,w);
    }else {
        return tree[tree[R].l].cnt-tree[tree[L].l].cnt+query(tree[L].r,tree[R].r,mid+1,r,w);
    }
}
void add(int x,int y,int z){
  edge[++tot].to=y;
  edge[tot].w=z;
  edge[tot].Next=head[x];
  head[x]=tot;
}
void dfs1(int u,int f,int depth){
    d[u]=depth;
    fa[u]=f;
    siz[u]=1;
    for (int i=head[u];i;i=edge[i].Next){
        int v=edge[i].to;
        if (v==f)continue;
        dfs1(v,u,depth+1);
        dis[v]=edge[i].w;
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]])
            son[u]=v;
    }
}
void dfs2(int u,int t){
   top[u]=t;
   id[u]=++order;
   rk[order]=u;
  // cout<<dis[u]<<endl;
   inserts(0,1e9,root[order-1],root[order],dis[u]);
   if(!son[u])return;
   dfs2(son[u],t);
   for (int i=head[u];i;i=edge[i].Next)
   {
       int v=edge[i].to;
       if(v!=son[u] && v!=fa[u])
        dfs2(v,v);
   }
}
int query_line(int a,int b,int c){
  int ans=0;
  while(top[a]!=top[b]){
    if (d[top[a]]>d[top[b]])swap(a,b);
    ans+=query(root[id[top[b]]-1],root[id[b]],0,1e9,c);
    b=fa[top[b]];
  }
  if (d[a]>d[b])swap(a,b);
  ans+=query(root[id[a]],root[id[b]],0,1e9,c);
  return ans;
}
int main(){
  int w,op,n,uu,vv;
  scanf("%d%d",&n,&op);
  tot=0;
  cnt=0;
  order=0;
  for (int i=1;i<n;i++){
     scanf("%d%d%d",&uu,&vv,&w);
     add(uu,vv,w);
     add(vv,uu,w);
  }
  dfs1(1,0,1);
  dfs2(1,1);
//  cout<<endl;
//  for (int i=1;i<=n;i++){
//    cout<<dis[i]<<"--";
//  }
//  cout<<endl;
//  cout<<endl;
//  for (int i=1;i<=n;i++){
//    cout<<"--"<<id[i]<<endl;
//  }
  while(op--){
    scanf("%d%d%d",&uu,&vv,&w);
    printf("%d\n",w?query_line(uu,vv,w):0);
  }
  return 0;
}

原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11397301.html

时间: 2024-07-31 11:04:08

2019年ICPC南昌网络赛 J. Distance on the tree 树链剖分+主席树的相关文章

2019 ICPC 南昌网络赛

2019 ICPC 南昌网络赛 比赛时间:2019.9.8 比赛链接:The 2019 Asia Nanchang First Round Online Programming Contest 总结 // 史上排名最高一次,开场不到两小时队友各A一题加水题共四题,排名瞬间升至三四十名 // 然后后三小时就自闭了,一题都没有突破...最后排名211 hhhh ? ? B. Fire-Fighting Hero 题意 队友做的,待补. ? AC代码 #include<cstdio> #includ

2019 ICPC 南昌网络赛 - Subsequence (子串判断,预处理,超时)

?? ?? ?? 题意:一个字符串s,t个字符串p,判断p是不是s的子序列 预处理出对于字符串s,每个位置i之后第一个字母x的位置,匹配子序列的时候就相当于在母串上往后跳,如果跳到母串末尾,子序列还没有结束,匹配失败. 然而!超时了QAQ,只能过八组样例,网上也只能找到过九组的,,,希望有哪位大神路过指点一下了 int tag[33],nxt[MAXN][30]; char s[MAXN],p[MAXN]; void init() { int n=strlen(s); for(int j=0;j

2019 ICPC 南昌网络赛 - Max answer (区间和,区间最值)

?? ???? 题意:价值 = 区间和 × 区间最小值,求数组的子区间的最大价值 (1)区间和---->前缀和 (2)O(n^2) 枚举区间 ---> O( n ) 枚举元素,根据当前元素查询相应区间和 对每个元素,维护他作为最小值的左右端点,枚举数组中的元素,该元素大于0为例,查找( i , r [ i ] )的前缀和最大值,( l [ i ] - 1 , i - 1 )的前缀和最小值,注意这里 l [ i ] -1 可能会小于1 ,ST表应从0开始维护 丧心病狂的压行QWQ ll a[MA

ACM-ICPC 2018 焦作赛区网络预赛 E Jiu Yuan Wants to Eat (树链剖分+线段树)

题目链接:https://nanti.jisuanke.com/t/31714 题意:给你一棵树,初始全为0,有四种操作: 1.u-v乘x    2.u-v加x   3. u-v取反  4.询问u-v的和 思路: 除去第三个操作就是很简单的树链剖分+线段树多重标记下放,所以我们只要考虑怎么维护第三个操作就好了, 由题目给的取反可知:!x =  (2^64-1) - x;   但是这样维护还是很麻烦,因为这道题是对2^64取模的,我们可以 尝试把这个式子转换成只有加法和乘法的,这样就可以将其和前面

ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval

ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval 题目大意:给一个长度为n,值域为[1, n]的序列{a},要求支持m次操作: 单点修改 1 pos val 询问子区间中某个值域的数的个数,连续的相同数字只记为一个.(即统计数字段的个数) 2 L R x y 数据范围: 1 ≤ n,m ≤ 2×10^5 1 ≤ a[i] ≤ n 解题思路: 连续重复的数字只记一次.所以考虑将每个数字段除第一个出现外的数字都删去(记为0).在读入操作的时候暴力模拟,同时维护

2018 ICPC 徐州网络赛

2018 ICPC 徐州网络赛 A. Hard to prepare 题目描述:\(n\)个数围成一个环,每个数是\(0\)~\(2^k-1\),相邻两个数的同或值不为零,问方案数. solution 将环变成链,设\(f[i][0\)~\(2]\),分别表示与第一个数相同,与第一个数不同,与第一个数相同,与第一个数的反相同.然后\(dp\)即可. 时间复杂度:\(O(n)\) B. BE, GE or NE solution 根据题目描述\(dp\)即可. 时间复杂度:\(O(nm)\) C.

西电校赛网络赛J题 lucas定理计算组合数

西电校赛网络赛J题  lucas定理计算组合数 问题 J: 找规律II 时间限制: 1 Sec  内存限制: 128 MB 提交: 96  解决: 16 [提交][状态][讨论版] 题目描述 现有数阵如下: 1    2  3   4     5    6 1   3   6  10  15 1   4  10   20 1   5   15 1    6 1 求这个数阵的第n行m列是多少(行列标号从1开始) 结果对10007取模 输入 多组数据,每组数据一行,包含两个整数n,m(1<=n<=

2015沈阳网络赛1003 Minimum Cut 树链剖分 数组维护前缀和进行区间增减

2015沈阳网络赛1003  Minimum Cut   树链剖分 数组维护前缀和进行区间增减 Minimum Cut Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)Total Submission(s): 0    Accepted Submission(s): 0 Problem Description Given a simple unweighted graph G 

2016湖南省赛 I Tree Intersection(线段树合并,树链剖分)

2016湖南省赛 I Tree Intersection(线段树合并,树链剖分) 传送门:https://ac.nowcoder.com/acm/contest/1112/I 题意: 给你一个n个结点的树,树上每个节点有自己的颜色 问你删除第i条边后形成的两颗子树有多少个相同的颜色 题解: 树链剖分写法: 对于每一种颜色来说,如果这个颜色是在单独的一颗子树中,那么就不会对其他的边产生贡献,所以我们单独对每一种颜色对边的贡献讨论,如果这个颜色只有一个,那么就不会产生贡献,否则,他就可以在两个相同颜