bzoj 3697: 采药人的路径
点分治自己水的题(以为这辈子也做不出点分治了23333)(此题坑爹,需要LL)
考虑这道题,需要求出的是01数量相同搞的路径,而且,需要有一个休息点(这个有意思)
我们来分析这个休息点,我们设一条路径满足要求,那么休息点也就从起点到休息点01相同。那么来处理休息点。
开始打标记。标记从根节点走过的一个路径和d,现在的点x,那么只需要的是在根节点到x的路径上再有一个点的距离为x即可,那么那个点就可以作为休息点。
所以,我们设t[?+N][0/1](设0的路径权值为-1,1的为1,所以?需要加个常数N)为距离根节点距离为?,1表示中间有休息点,0表示没有休息点。那么答案就是t[N-?][1/0]
如果中间有休息点,就加t[N-?][0]+t[N-?][1],如果没有,那么就只能加t[N-?][1],统计答案和bzoj2599的方法相似(下一篇会有)(貌似变成心机婊了2333)
1 #include<bits/stdc++.h> 2 #define N 100005 3 #define M 10000005 4 #define LL long long 5 #define inf 0x3f3f3f3f 6 using namespace std; 7 inline int ra() 8 { 9 int x=0,f=1; char ch=getchar(); 10 while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} 11 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 12 return x*f; 13 } 14 struct node{ 15 int to,next,v; 16 }e[N<<1]; 17 int size[N],f[N],d[N],n,head[N],cnt,sum,root; 18 LL ans,t[N<<1][3]; 19 bool vis[N]; int inq[N<<1]; 20 void insert(int x, int y, int v) 21 { 22 e[++cnt].next=head[x]; e[cnt].to=y; e[cnt].v=v; head[x]=cnt; 23 } 24 void getroot(int x, int fa) 25 { 26 size[x]=1; f[x]=0; 27 for (int i=head[x];i;i=e[i].next) 28 { 29 if (vis[e[i].to] || e[i].to==fa) continue; 30 getroot(e[i].to,x); 31 size[x]+=size[e[i].to]; 32 f[x]=max(f[x],size[e[i].to]); 33 } 34 f[x]=max(f[x],sum-size[x]); 35 if (f[x]<f[root]) root=x; 36 } 37 void cal(int x, int fa) 38 { 39 if (inq[d[x]+N]) 40 ans+=t[N-d[x]][1]+t[N-d[x]][0]; 41 else ans+=t[N-d[x]][1]; 42 inq[d[x]+N]++; 43 for (int i=head[x];i;i=e[i].next) 44 { 45 if (e[i].to==fa || vis[e[i].to]) continue; 46 d[e[i].to]=d[x]+e[i].v; 47 cal(e[i].to,x); 48 } 49 inq[d[x]+N]--; 50 } 51 void add(int x, int fa, int flag) 52 { 53 if (flag) { 54 if (inq[d[x]+N]) t[d[x]+N][1]++; 55 else t[d[x]+N][0]++; 56 } 57 else t[d[x]+N][1]=t[d[x]+N][0]=0; 58 inq[d[x]+N]++; 59 for (int i=head[x];i;i=e[i].next) 60 if (!vis[e[i].to] && fa!=e[i].to) 61 add(e[i].to,x,flag); 62 inq[d[x]+N]--; 63 } 64 void work(int x) 65 { 66 vis[x]=1; t[N][0]=1; 67 for (int i=head[x];i;i=e[i].next) 68 { 69 if (vis[e[i].to]) continue; 70 d[e[i].to]=e[i].v; 71 cal(e[i].to,0); 72 inq[N]=1; 73 add(e[i].to,0,1); 74 inq[N]=0; 75 } 76 for (int i=head[x];i;i=e[i].next) 77 if (!vis[e[i].to]) add(e[i].to,0,0); 78 for (int i=head[x];i;i=e[i].next) 79 { 80 if (vis[e[i].to]) continue; 81 root=0; sum=size[e[i].to]; 82 getroot(e[i].to,0); 83 work(root); 84 } 85 } 86 int main() 87 { 88 n=ra(); 89 for (int i=1; i<n; i++) 90 { 91 int x=ra(),y=ra(),v=ra(); 92 if (v==0) v=-1; 93 insert(x,y,v); insert(y,x,v); 94 } 95 sum=f[0]=n; 96 getroot(1,0); 97 work(root); 98 cout<<ans; 99 return 0; 100 }