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;}