这道在没加读入优化时间在20s左右的题终于在大米饼两天的死缠烂打、鬼混、乱整乱撞后艰难地AC了。但惋惜的是,大米饼一号代码其实更加简洁,但至今找不出BUG,我将它放在下面,也许有一天从远方来的另一个大米饼会拯救它。让我们一起念出这道题的关键字:

Kurskal,LCA倍增,Kurskal重构树,dfs序,主席树。

比较新鲜的是重构树,它有一些美妙性质。

【Peaks加强版 BZOJ 3551】你被坑了吗?

红色的是由边化成的节点。用Kurskal建出这棵树,在这一棵树上进行DFS序处理,并且在DFS序上进行主席树(可持久化线段树)处理。有趣的是,这道题读入优化可以加速5s,是不是很美妙!

 

1 #include<stdio.h> 2 #include<algorithm> 3 #include<cstring> 4 #define ro(i,a,b) for(int i=a;i>=b;i--) 5 #define go(i,a,b) for(int i=a;i<=b;i++) 6 using namespace std; 7 const int inf=2147483646;const int logp=18;const int N=1e5+233; 8 const int M=5e5+233;const int P=N<<1;const int E=P<<1;const int S=P*logp ; 9 int n,m,q,p,num,cnt,K,d[N],h[N],dad[P],val[P],rt[P],lc[S],rc[S],sum[S]; 10 int si[P],dep[P],dfn[P],pos[P],head[P],nex[E],ver[E],fa[logp+1][P],pr[logp+1],lg[P]; 11 struct edge{int x,y,z;};edge a[M]; 12 bool cmp(edge a, edge b){return a.z<b.z;} 13 int find(int x){return dad[x]!=x?dad[x]=find(dad[x]):x;} 14 void ADD(int u, int v){nex[++K]=head[u];head[u]=K;ver[K]=v;} 15 void dfs(int u) 16 { 17 si[u]=1;dfn[u]=++num;pos[num]=u; 18 for(int i=head[u];i;i=nex[i]) 19 {int v=ver[i];fa[0][v]=u;dep[v]=dep[u]+1;dfs(v);si[u]+=si[v];} 20 } 21 void Kruskal() 22 { 23 p=n;sort(a+1,a+1+m,cmp); 24 go(i,1,m){int x=find(a[i].x),y=find(a[i].y); 25 if(x!=y){dad[++p]=p;val[p]=a[i].z;dad[x]=dad[y]=p; 26 ADD(p,x),ADD(p,y);if(p==(n<<1)-1)break;}} 27 } 28 void Rmq() 29 { 30 go(k,1,lg[p])go(i,1,p){if(dep[i]<pr[k])continue; 31 fa[k][i]=fa[k-1][fa[k-1][i]];} 32 } 33 int Add(int p,int l,int r,int x) 34 { 35 int k=++cnt;sum[k]=sum[p]+1;if(l==r)return k;int mid=l+r>>1; 36 if(x<=mid)lc[k]=Add(lc[p],l,mid,x),rc[k]=rc[p]; 37 else rc[k]=Add(rc[p],mid+1,r,x),lc[k]=lc[p];return k; 38 } 39 void prepare() 40 { 41 Kruskal();num=0;go(i,1,p)if(!dfn[i])dfs(find(i));pr[0]=1; 42 go(i,1,logp){pr[i]=pr[i-1]<<1;if(pr[i]>p)break;lg[pr[i]]=1;} 43 go(i,1,p)lg[i]+=lg[i-1];Rmq();go(i,1,num) 44 {int x=pos[i];if(x>n)rt[i]=rt[i-1];else rt[i]=Add(rt[i-1],1,n,h[x]);} 45 } 46 int Jump(int x, int v){ 47 int len=lg[dep[x]];ro(i,len,0)if(val[fa[i][x]]<=v)x=fa[i][x];return x; 48 } 49 int Query(int a, int b, int l, int r, int k) 50 { 51 if(l==r)return l;int amo=sum[rc[b]]-sum[rc[a]]; 52 int mi=l+r>>1;if(amo<k)return Query(lc[a],lc[b],l,mi,k-amo); 53 return Query(rc[a],rc[b],mi+1,r,k); 54 } 55 int Ask(int x, int v, int k) 56 { 57 int anc=Jump(x,v),beg=rt[dfn[anc]-1],end=rt[dfn[anc]+si[anc]-1]; 58 if(sum[end]-sum[beg]<k)return -1; 59 int hi=Query(beg,end,1,n,k);return d[hi]; 60 } 61 int main() 62 { 63 scanf("%d%d%d",&n,&m,&q);val[0]=inf; 64 go(i,1,n)scanf("%d",&h[i]),d[i]=h[i],dad[i]=i; 65 sort(d+1,d+1+n);go(i,1,n)h[i]=lower_bound(d+1,d+1+n,h[i])-d; 66 go(i,1,m)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); 67 prepare();int ans=-1;while(q--) 68 { 69 int x,v,k;scanf("%d%d%d",&x,&v,&k); 70 if(ans != -1)x^=ans,v^=ans,k^=ans; 71 ans=Ask(x,v,k);printf("%d\n",ans); 72 } 73 }
【大米饼代码】

相关文章:

  • 2021-08-10
  • 2021-10-09
  • 2021-11-22
  • 2021-05-21
  • 2022-01-26
  • 2022-02-01
  • 2021-12-20
  • 2021-12-29
猜你喜欢
  • 2022-01-12
  • 2021-12-16
  • 2021-11-30
  • 2021-06-13
  • 2022-03-04
  • 2021-12-05
相关资源
相似解决方案