[关闭]
@ysner 2018-07-17T09:47:41.000000Z 字数 7994 阅读 1854

酪奶

树上差分 二分


题面

给一棵个点、条边的基环树,钦定要走环就必须要经过某条边,因此两点间路径唯一。边有边权,现有次行动,每次将两点间路径上的边权同时减去一值,问第几次行动后出现负边权。

吐槽

毒瘤出题人坑害机房多位大佬,出现多人怒码的惨状。
好像我也只有10分

解析

算法

把图看成根节点连成一个环的几颗树的集合。
暴力模拟即可。
复杂度
然而打不对。。。

算法

可以用一颗线段树维护整个环的边权。

算法

线段树维护环,树剖+线段树维护几颗树。
即数据结构优化后的模拟
复杂度降到
据说码量可以达到???

还有一种方法。
去掉钦定边,图就变成了一棵树。把该边一个点作为树的根,另一点为
如果两点路径不经过环,直接修改即可。
如果经过,修改一个点到路径,另一点到的路径和那条钦定边。
判断方法是两点与在树上的(分别代表着两点进入环时到的点)不同,如果深度小就连,大就连
复杂度同,但常数肯定小一些,因不需要线段树。

表求

原理:在序中,两个点的出现在两个点第一次出现的位置之间,且为中间这些数中深度最小的点。
显然。

  1. il void dfs(re int u,re int deep)
  2. {
  3. id[u]=++top;sta[top]=u;d[top]=deep;
  4. for(re int i=h[u];i+1;i=e[i].nxt)
  5. {
  6. re int v=e[i].to;
  7. if(id[v]) continue;
  8. dfs(v,deep+1);
  9. sta[++top]=u;d[top]=deep;
  10. }
  11. }
  12. int main()
  13. {
  14. memset(h,-1,sizeof(h));
  15. n=gi();q=gi();rt=gi();
  16. fp(i,1,n-1)
  17. {
  18. re int u=gi(),v=gi();
  19. add(u,v);add(v,u);
  20. }
  21. dfs(rt,1);
  22. fp(i,1,top) f[0][i]=d[i],dp[0][i]=sta[i];
  23. for(re int i=1;i<=log(top)/log(2);i++)
  24. for(re int j=1;j<=top-(1<<i)+1;j++)
  25. {
  26. if(f[i-1][j]<f[i-1][j+(1<<(i-1))]) f[i][j]=f[i-1][j],dp[i][j]=dp[i-1][j];
  27. else f[i][j]=f[i-1][j+(1<<(i-1))],dp[i][j]=dp[i-1][j+(1<<(i-1))];
  28. }
  29. //printf("good\n");
  30. fp(i,1,q)
  31. {
  32. re int l=gi(),r=gi();
  33. l=id[l],r=id[r];
  34. if(l>r) swap(l,r);
  35. re int k=0;
  36. while((1<<k)<=r-l+1) ++k;
  37. --k;
  38. if(f[k][l]<f[k][r-(1<<k)+1]) printf("%d\n",dp[k][l]);
  39. else printf("%d\n",dp[k][r-(1<<k)+1]);
  40. }
  41. return 0;
  42. }

算法

此题原型借教室。
毒瘤改了一下变成在基环树边上建教室。。。。

于是我们可以发现,我们可以用树上差分来维护树上边权。
给两点之间的路径权值的具体做法,就变成了在两个点上都打上的标记,再在上打的标记。
当然,打上所有标记后我们是不能得到某一步后(过程中)的边权的。
所以我们要用二分答案来逼近出现负边权的确切次数。

然而,求和求次操作后的边权都是复杂度瓶颈,复杂度可达
注意到二分时每次重求边权未免过于浪费,可以在上一次的基础上继续打标记(往前推就打反标记),再继续推。复杂度可降为


在此题中,求任意两点间的,在线算法树剖和倍增复杂度都会达到表求预处理复杂度,在线
总复杂度

作为一只懒于打数据结构的蒟蒻,我当然选择方法二啦
树链剖分求,期望得分

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<algorithm>
  7. #define ll long long
  8. #define re register
  9. #define il inline
  10. #define ls x<<1
  11. #define rs x<<1|1
  12. #define max(a,b) ((a)>(b)?(a):(b))
  13. #define min(a,b) ((a)<(b)?(a):(b))
  14. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  15. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  16. using namespace std;
  17. const int N=1e5+100;
  18. unsigned int SA,SB,SC;
  19. int n,m,h[N],cnt,hu,hv,hw,rt,d[N],f[N],sz[N],son[N],top[N],L[N],R[N],id[N],tim,las,c[N],flag=0;
  20. bool vis[N<<1];
  21. struct dat{int u,v,w,tag,lca,gen,lca1;}a[N*100];
  22. struct Edge{int to,nxt,w,id;}e[N<<1];
  23. il void add(re int u,re int v,re ll w,re int id){e[++cnt]=(Edge){v,h[u],w,id};h[u]=cnt;}
  24. il ll gi()
  25. {
  26. re ll x=0,t=1;
  27. re char ch=getchar();
  28. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  29. if(ch=='-') t=-1,ch=getchar();
  30. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  31. return x*t;
  32. }
  33. unsigned int rng61()
  34. {
  35. SA^=SA<<16;SA^=SA>>5;SA^=SA<<1;
  36. unsigned int t=SA;
  37. SA=SB;SB=SC;SC^=t^SA;
  38. return SC;
  39. }
  40. il void dfs1(re int u,re int fa)
  41. {
  42. d[u]=d[fa]+1;f[u]=fa;sz[u]=1;
  43. for(re int i=h[u];i+1;i=e[i].nxt)
  44. {
  45. re int v=e[i].to;
  46. if(v==fa) continue;
  47. dfs1(v,u);
  48. sz[u]+=sz[v];
  49. if(sz[son[u]]<sz[v]) son[u]=v;
  50. }
  51. }
  52. il void dfs2(re int u,re int up)
  53. {
  54. top[u]=up;L[u]=++tim;id[tim]=u;
  55. if(son[u]) dfs2(son[u],up);
  56. for(re int i=h[u];i+1;i=e[i].nxt)
  57. {
  58. re int v=e[i].to;
  59. if(v==f[u]||v==son[u]) continue;
  60. dfs2(v,v);
  61. }
  62. R[u]=tim;
  63. }
  64. il int getlca(re int u,re int v)
  65. {
  66. while(top[u]^top[v])
  67. {
  68. if(d[top[u]]<d[top[v]]) swap(u,v);
  69. u=f[top[u]];
  70. }
  71. return d[u]<d[v]?u:v;
  72. }
  73. il void dfs(re int u,re int fa)
  74. {
  75. for(re int i=h[u];i+1;i=e[i].nxt)
  76. {
  77. re int v=e[i].to;
  78. if(v==fa) continue;
  79. dfs(v,u);
  80. c[u]+=c[v];
  81. e[i].w+=c[v];
  82. c[v]=0;
  83. if(e[i].w<0) flag=1,vis[e[i].id]=1;else vis[e[i].id]=0;
  84. }
  85. }
  86. il int check(re int x)
  87. {
  88. flag=0;
  89. if(las<x)
  90. {
  91. fp(i,las+1,x)
  92. {
  93. re int u=a[i].u,v=a[i].v,w=a[i].w,lca=a[i].lca,gen=a[i].gen,lca1=a[i].lca1;
  94. if(a[i].tag) c[u]-=w,c[v]-=w,c[lca]+=2*w;
  95. else c[gen]-=w,c[rt]+=w,c[lca]-=w,c[hv]-=w,c[lca1]+=2*w,hw-=w;
  96. }
  97. dfs(rt,0);
  98. if(hw<0) flag=1,vis[1]=1;else vis[1]=0;
  99. }
  100. else
  101. {
  102. fq(i,las,x+1)
  103. {
  104. re int u=a[i].u,v=a[i].v,w=a[i].w,lca=a[i].lca,gen=a[i].gen,lca1=a[i].lca1;
  105. if(a[i].tag) c[u]+=w,c[v]+=w,c[lca]-=2*w;
  106. else c[gen]+=w,c[rt]-=w,c[lca]+=w,c[hv]+=w,c[lca1]-=2*w,hw+=w;
  107. }
  108. dfs(rt,0);
  109. if(hw<0) flag=1,vis[1]=1;else vis[1]=0;
  110. }
  111. las=x;
  112. return flag;
  113. }
  114. int main()
  115. {
  116. freopen("eseehc.in","r",stdin);
  117. freopen("eseehc.out","w",stdout);
  118. memset(h,-1,sizeof(h));
  119. SA=gi();SB=gi();SC=gi();n=gi();m=gi();
  120. fp(i,1,m) a[i].u=rng61()%n+1,a[i].v=rng61()%n+1,a[i].w=rng61()%100+1;
  121. fp(i,1,n)
  122. {
  123. re int u=gi(),v=gi(),w=gi();
  124. if(i==1) rt=hu=u,hv=v,hw=w;
  125. else add(u,v,w,i),add(v,u,w,i);
  126. }
  127. dfs1(rt,0);dfs2(rt,rt);
  128. fp(i,1,m)
  129. {
  130. re int u=a[i].u,v=a[i].v;
  131. a[i].tag=(getlca(u,hv)==getlca(v,hv));
  132. if(a[i].tag) a[i].lca=getlca(u,v);
  133. else if(d[getlca(v,hv)]>=d[getlca(u,hv)]) a[i].gen=u,a[i].lca=v,a[i].lca1=getlca(v,hv);
  134. else a[i].gen=v,a[i].lca=u,a[i].lca1=getlca(u,hv);
  135. //printf("%d %d %d %d %d %d\n",u,v,a[i].tag,a[i].lca,getlca(u,hv),getlca(v,hv));
  136. }
  137. re int l=0,r=m+100;
  138. while(l<r)
  139. {
  140. re int mid=l+r>>1;
  141. if(check(mid)) r=mid;
  142. else l=mid+1;
  143. }
  144. if(r==m+100) puts("-1");
  145. else
  146. {
  147. check(r);
  148. printf("%d\n",r);
  149. fp(i,1,n) if(vis[i]) printf("%d ",i);
  150. puts("");
  151. }
  152. fclose(stdin);
  153. fclose(stdout);
  154. return 0;
  155. }

注意到几个细节。
可能你在退出二分时,保留的状态是时的状态,导致找不到边权的边。
所以输出答案前要把状态推到答案那一步。

并且将差分标记上传后要清!!!

没调完的表求,期望

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<algorithm>
  7. #define ll long long
  8. #define re register
  9. #define il inline
  10. #define ls x<<1
  11. #define rs x<<1|1
  12. #define max(a,b) ((a)>(b)?(a):(b))
  13. #define min(a,b) ((a)<(b)?(a):(b))
  14. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  15. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  16. using namespace std;
  17. const int N=1e5+100;
  18. unsigned int SA,SB,SC;
  19. int n,m,h[N],cnt,hu,hv,hw,rt,d[N],dd[N],sta[N<<2],top,dp[20][N<<2],f[20][N<<2],id[N],las,flag=0,c[N];
  20. bool vis[N<<1];
  21. struct dat{int u,v,w,tag,lca,gen,lca1;}a[N*100];
  22. struct Edge{int to,nxt,w,id;}e[N<<1];
  23. il void add(re int u,re int v,re ll w,re int id){e[++cnt]=(Edge){v,h[u],w,id};h[u]=cnt;}
  24. il ll gi()
  25. {
  26. re ll x=0,t=1;
  27. re char ch=getchar();
  28. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  29. if(ch=='-') t=-1,ch=getchar();
  30. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  31. return x*t;
  32. }
  33. unsigned int rng61()
  34. {
  35. SA^=SA<<16;SA^=SA>>5;SA^=SA<<1;
  36. unsigned int t=SA;
  37. SA=SB;SB=SC;SC^=t^SA;
  38. return SC;
  39. }
  40. il void dfs(re int u,re int fa)
  41. {
  42. for(re int i=h[u];i+1;i=e[i].nxt)
  43. {
  44. re int v=e[i].to;
  45. if(v==fa) continue;
  46. dfs(v,u);
  47. c[u]+=c[v];
  48. e[i].w+=c[v];
  49. c[v]=0;
  50. if(e[i].w<0) flag=1,vis[e[i].id]=1;else vis[e[i].id]=0;
  51. }
  52. }
  53. il void dfs1(re int u,re int deep)
  54. {
  55. //printf("%d %d\n",u,deep);
  56. id[u]=++top;sta[top]=u;d[top]=deep;dd[u]=deep;
  57. for(re int i=h[u];i+1;i=e[i].nxt)
  58. {
  59. re int v=e[i].to;
  60. if(id[v]) continue;
  61. dfs1(v,deep+1);
  62. sta[++top]=u;d[top]=deep;
  63. }
  64. }
  65. il int getlca(re int l,re int r)
  66. {
  67. l=id[l],r=id[r];
  68. if(l>r) swap(l,r);
  69. re int k=0;
  70. while((1<<k)<=r-l+1) ++k;
  71. --k;
  72. if(f[k][l]<f[k][r-(1<<k)+1]) return dp[k][l];
  73. else return dp[k][r-(1<<k)+1];
  74. }
  75. il int check(re int x)
  76. {
  77. flag=0;
  78. if(las<x)
  79. {
  80. fp(i,las+1,x)
  81. {
  82. re int u=a[i].u,v=a[i].v,w=a[i].w,lca=a[i].lca,gen=a[i].gen,lca1=a[i].lca1;
  83. if(a[i].tag) c[u]-=w,c[v]-=w,c[lca]+=2*w;
  84. else c[gen]-=w,c[rt]+=w,c[lca]-=w,c[hv]-=w,c[lca1]+=2*w,hw-=w;
  85. }
  86. dfs(rt,0);
  87. if(hw<0) flag=1,vis[1]=1;else vis[1]=0;
  88. }
  89. else
  90. {
  91. fq(i,las,x+1)
  92. {
  93. re int u=a[i].u,v=a[i].v,w=a[i].w,lca=a[i].lca,gen=a[i].gen,lca1=a[i].lca1;
  94. if(a[i].tag) c[u]+=w,c[v]+=w,c[lca]-=2*w;
  95. else c[gen]+=w,c[rt]-=w,c[lca]+=w,c[hv]+=w,c[lca1]-=2*w,hw+=w;
  96. }
  97. dfs(rt,0);
  98. if(hw<0) flag=1,vis[1]=1;else vis[1]=0;
  99. }
  100. las=x;
  101. return flag;
  102. }
  103. int main()
  104. {
  105. freopen("eseehc.in","r",stdin);
  106. freopen("eseehc.out","w",stdout);
  107. memset(h,-1,sizeof(h));
  108. SA=gi();SB=gi();SC=gi();n=gi();m=gi();
  109. fp(i,1,m) a[i].u=rng61()%n+1,a[i].v=rng61()%n+1,a[i].w=rng61()%100+1;
  110. fp(i,1,n)
  111. {
  112. re int u=gi(),v=gi(),w=gi();
  113. if(i==1) rt=hu=u,hv=v,hw=w;
  114. else add(u,v,w,i),add(v,u,w,i);
  115. }
  116. dfs1(rt,1);
  117. fp(i,1,top) f[0][i]=d[i],dp[0][i]=sta[i];
  118. for(re int i=1;i<=log(top)/log(2);i++)
  119. for(re int j=1;j<=top-(1<<i)+1;j++)
  120. if(f[i-1][j]<f[i-1][j+(1<<(i-1))]) f[i][j]=f[i-1][j],dp[i][j]=dp[i-1][j];
  121. else f[i][j]=f[i-1][j+(1<<(i-1))],dp[i][j]=dp[i-1][j+(1<<(i-1))];
  122. fp(i,1,m)
  123. {
  124. re int u=a[i].u,v=a[i].v;
  125. a[i].tag=(getlca(u,hv)==getlca(v,hv));
  126. if(a[i].tag) a[i].lca=getlca(u,v);
  127. else if(dd[getlca(v,hv)]>=dd[getlca(u,hv)]) a[i].gen=u,a[i].lca=v,a[i].lca1=getlca(v,hv);
  128. else a[i].gen=v,a[i].lca=u,a[i].lca1=getlca(u,hv);
  129. //printf("%d %d %d %d %d %d\n",u,v,a[i].tag,a[i].lca,getlca(u,hv),getlca(v,hv));
  130. }
  131. re int l=0,r=m+100;
  132. while(l<r)
  133. {
  134. re int mid=l+r>>1;
  135. if(check(mid)) r=mid;
  136. else l=mid+1;
  137. }
  138. if(r==m+100) puts("-1");
  139. else
  140. {
  141. check(r);
  142. printf("%d\n",r);
  143. fp(i,1,n) if(vis[i]) printf("%d ",i);
  144. puts("");
  145. }
  146. fclose(stdin);
  147. fclose(stdout);
  148. return 0;
  149. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注