COJ 0346 WZJ的旅行(二)更新动态树分治版本

WZJ的旅行(二)
难度级别:D; 运行时间限制:3000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
试题描述

时隔多日,WZJ又来到了幻想国旅行。幻想国由N个城市组成,由于道路翻修,只有N-1条双向道路可以通行,第i条双向道路从ui连接到vi,距离为wi。但这N-1条道路竟然连接了整个国家,每两个城市之间都有一条道路!

WZJ知道这里景点很多,所以他想从城市s出发到城市t,旅游所有沿途的城市。WZJ想起到锻炼作用,但又不想太累,所以城市s到城市t的距离必须在L到R之间。另外WZJ规定s必须小于t,你能帮助他统计有多少对城市(s,t)符合要求吗?

输入
第一行为三个正整数N,L,R。
接下来N-1行每行为三个正整数ui,vi,wi。 
输出
输出多少对城市(s,t)符合要求。
输入示例
5 3 6
1 2 3
2 3 3
3 4 2
4 5 1
输出示例
6
其他说明
城市对(1,2)、(2,3)、(1,3)、(2,4)、(2,5)、(3,5)均符合要求,共计6对
1<=N<=100000
1<=L<=R<=10^9
1<=ui,vi<=N
1<=wi<=1000

题解:会写点分治了。。。

首先补集转换,不在同一个子树的 = 总的 - 在同一个子树的,那么就是求路径两段在同一个子树的,dfs一遍排序再金鸡独立大法求前缀,转成区间,然后就没了。

意会一下。。。(逃。。。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<cstring>
 7 #define PAU putchar(' ')
 8 #define ENT putchar('
')
 9 using namespace std;
10 const int maxn=100000+10,inf=-1u>>1;
11 struct ted{int x,y,w;ted*nxt;}adj[maxn<<1],*fch[maxn],*ms=adj;
12 void add(int w,int y,int x){
13     *ms=(ted){x,y,w,fch[x]};fch[x]=ms++;
14     *ms=(ted){y,x,w,fch[y]};fch[y]=ms++;
15     return;
16 }
17 bool vis[maxn];
18 int L,R,CG=1,siz[maxn],f[maxn],n,size;
19 void findcg(int x,int fa){
20     int mxs=-inf;siz[x]=1;
21     for(ted*e=fch[x];e;e=e->nxt){
22         int v=e->y;if(v!=fa&&!vis[v]){
23             findcg(v,x);siz[x]+=siz[v];
24             mxs=max(mxs,siz[v]);
25         }
26     }f[x]=max(mxs,size-siz[x]);
27     if(f[x]<f[CG])CG=x;return;
28 }
29 long long ans;
30 int A[maxn],dep[maxn],cnt;
31 void dfs(int x,int fa,int dist){
32     A[cnt++]=dist;
33     for(ted*e=fch[x];e;e=e->nxt){
34         int v=e->y;if(v!=fa&&!vis[v])dfs(v,x,dist+e->w);
35     }return;
36 }
37 long long cal(int x,int base){
38     cnt=0;dfs(x,0,base);long long res=0;
39     sort(A,A+cnt);
40     int l=0,r=cnt-1;while(l<r)if(A[l]+A[r]>R)r--;else res+=r-l++;
41     l=0;r=cnt-1;while(l<r)if(A[l]+A[r]>=L)r--;else res-=r-l++;
42     return res;
43 }
44 void solve(int x){
45     vis[x]=true;ans+=cal(x,0);
46     for(ted*e=fch[x];e;e=e->nxt){
47         int v=e->y;if(!vis[v]){
48             ans-=cal(v,e->w);
49             f[CG=0]=inf;size=siz[v];findcg(v,0);
50             solve(CG);
51         }
52     }return;
53 }
54 inline int read(){
55     int x=0,sig=1;char ch=getchar();
56     while(!isdigit(ch)){if(ch=='-') sig=-1;ch=getchar();}
57     while(isdigit(ch)) x=10*x+ch-'0',ch=getchar();
58     return x*=sig;
59 }
60 inline void write(long long x){
61     if(x==0){putchar('0');return;}if(x<0) putchar('-'),x=-x;
62     int len=0;long long buf[15];while(x) buf[len++]=x%10,x/=10;
63     for(int i=len-1;i>=0;i--) putchar(buf[i]+'0');return;
64 }
65 void init(){
66     n=read();L=read();R=read();
67     for(int i=1;i<n;i++)add(read(),read(),read());
68     f[CG=0]=inf;size=n;findcg(1,0);
69     solve(CG);write(ans);
70     return;
71 }
72 void work(){
73     return;
74 }
75 void print(){
76     return;
77 }
78 int main(){
79     init();work();print();return 0;
80 }

当然窝萌还可以写动态树分治对不对,维护两个treap就是常数有点大耶。

要注意一点:cal函数只需要query就行了,不需要重新计算一遍!!!

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<cstring>
  7 #include<ctime>
  8 #define PAU putchar(' ')
  9 #define ENT putchar('
')
 10 #define CH for(int d=0;d<2;d++)if(ch[d])
 11 using namespace std;
 12 const int maxn=100000+10,maxq=200000+10,maxnode=4000000+10,maxm=200000+10,inf=-1u>>1;
 13 struct node{
 14     node*ch[2];int r,siz,v;
 15     void init(){r=rand();siz=1;ch[0]=ch[1]=NULL;return;}
 16     void update(){siz=1;CH{siz+=ch[d]->siz;}return;}
 17 }treap[maxnode],*nodecnt=treap,*cha[maxn],*tre[maxn];
 18 node*newnode(){node*x=nodecnt++;x->init();return x;}
 19 void rotate(node*&x,int d){
 20     node*k=x->ch[d^1];x->ch[d^1]=k->ch[d];k->ch[d]=x;x->update();k->update();x=k;return;
 21 }
 22 void insert(node*&x,int v){
 23     if(!x)x=newnode(),x->v=v;
 24     else{int d=v>x->v;insert(x->ch[d],v);
 25         if(x->r<x->ch[d]->r)rotate(x,d^1);else x->update();
 26     }return;
 27 }
 28 int find(node*x,int v){
 29     if(!x)return 0;
 30     if(v<=x->v)return find(x->ch[0],v);
 31     else return (x->ch[0]?x->ch[0]->siz:0)+1+find(x->ch[1],v);
 32 }
 33 struct ted{int x,y,w;ted*nxt;}adj[maxm],*fch[maxn],*ms=adj;
 34 void add(int x,int y,int w){
 35     *ms=(ted){x,y,w,fch[x]};fch[x]=ms++;
 36     *ms=(ted){y,x,w,fch[y]};fch[y]=ms++;
 37     return;
 38 }
 39 int mi[maxq][20],Log[maxq],dep[maxn],pos[maxn],cnt;
 40 void build(int x,int fa,int dis){
 41     mi[++cnt][0]=dep[x]=dis;pos[x]=cnt;
 42     for(ted*e=fch[x];e;e=e->nxt){
 43         int v=e->y;if(v!=fa)build(v,x,dis+e->w),mi[++cnt][0]=dep[x];
 44     }return;
 45 }
 46 void initrmq(){
 47     Log[0]=-1;for(int i=1;i<=cnt;i++)Log[i]=Log[i>>1]+1;
 48     for(int j=1;(1<<j)<=cnt;j++)
 49         for(int i=1;i+(1<<j)-1<=cnt;i++)
 50             mi[i][j]=min(mi[i][j-1],mi[i+(1<<j-1)][j-1]);return;
 51 }
 52 int dist(int x,int y){
 53     int ans=dep[x]+dep[y];x=pos[x];y=pos[y];if(x>y)swap(x,y);
 54     int k=Log[y-x+1];return ans-2*min(mi[x][k],mi[y-(1<<k)+1][k]);
 55 }
 56 int CG,f[maxn],size,siz[maxn],fa[maxn];bool vis[maxn];
 57 void findcg(int x,int fa){
 58     siz[x]=1;int mxs=0;
 59     for(ted*e=fch[x];e;e=e->nxt){
 60         int v=e->y;if(v!=fa&&!vis[v]){
 61             findcg(v,x);siz[x]+=siz[v];mxs=max(mxs,siz[v]);
 62         }
 63     }f[x]=max(mxs,size-siz[x]);if(f[x]<f[CG])CG=x;return;
 64 }
 65 void dfs(int x,int fa){
 66     siz[x]=1;
 67     for(ted*e=fch[x];e;e=e->nxt){
 68         int v=e->y;if(v!=fa&&!vis[v])dfs(v,x),siz[x]+=siz[v];
 69     }return;
 70 }
 71 void solve(int x=CG){
 72     vis[x]=true;
 73     for(ted*e=fch[x];e;e=e->nxt){
 74         int v=e->y;if(!vis[v]){
 75             dfs(v,x);f[CG=0]=size=siz[v];findcg(v,x);fa[CG]=x;solve();
 76         }
 77     }return;
 78 }
 79 void update(int x){
 80     insert(tre[x],0);
 81     for(int ret=x;fa[x];x=fa[x]){
 82         int d=dist(ret,fa[x]);
 83         insert(tre[fa[x]],d);insert(cha[x],d);
 84     }return;
 85 }
 86 int k;
 87 int query(int x){
 88     int ans=find(tre[x],k);
 89     for(int ret=x;fa[x];x=fa[x]){
 90         int d=dist(ret,fa[x]);
 91         ans+=find(tre[fa[x]],k-d)-find(cha[x],k-d);
 92     }return ans;
 93 }
 94 int n,L,R;
 95 int cal(int t){
 96     k=t+1;int ans=0;for(int i=1;i<=n;i++)ans+=query(i);return ans;
 97 }
 98 inline int read(){
 99     int x=0,sig=1;char ch=getchar();
100     while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();}
101     while(isdigit(ch))x=10*x+ch-'0',ch=getchar();
102     return x*=sig;
103 }
104 inline void write(int x){
105     if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
106     int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
107     for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
108 }
109 void init(){
110     srand(time(0));
111     n=read();L=read(),R=read();int x,y;
112     for(int i=1;i<n;i++)x=read(),y=read(),add(x,y,read());build(1,0,0);initrmq();
113     f[CG=0]=size=n;findcg(1,0);solve();for(int i=1;i<=n;i++)update(i);
114     write((cal(R)-cal(L-1))>>1);
115     return;
116 }
117 void work(){
118     return;
119 }
120 void print(){
121     return;
122 }
123 int main(){init();work();print();return 0;}
原文地址:https://www.cnblogs.com/chxer/p/4696951.html