日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【kruskal重构树】【主席树】werewolf 狼人(P4899)

發(fā)布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【kruskal重构树】【主席树】werewolf 狼人(P4899) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

正題

P4899


題目大意

給你一個圖,對于每次詢問Si,Ei,Li,RiS_i,E_i,L_i,R_iSi?,Ei?,Li?,Ri?,回答從SiS_iSi?走到EiE_iEi?,是否存在路徑滿足前面一段只經(jīng)過Li~n?1L_i\sim n-1Li?n?1,后面一段只經(jīng)過0~Ri0\sim R_i0Ri?


解題思路

先正序倒序各建立一個Kruskal重構(gòu)樹

然后以dfnAdfn_AdfnA?建立主席樹,每個點的主席樹中在dfnBdfn_BdfnB?的位置+1

那么查詢時,直接查詢前面一段的主席樹中,后面一段的區(qū)間是否有值即可


code

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 400021 using namespace std; int n,m,q,x,y,l,r,w,s,t,xx,yy,tot,v[N],h[N],f[N],rt[N]; struct rec {int to,nx; }e[N<<1]; struct node {int nm,mx[N],mn[N],to1[N],to2[N],dfn[N],low[N],fa[N][20];void dfs(int x){for(int i=1;i<=16;++i)fa[x][i]=fa[fa[x][i-1]][i-1];if(!to1[x]){dfn[x]=low[x]=++nm;mx[x]=mn[x]=x;return;}dfn[x]=nm+1;fa[to1[x]][0]=x;fa[to2[x]][0]=x;dfs(to1[x]);dfs(to2[x]);mx[x]=max(mx[to1[x]],mx[to2[x]]);mn[x]=min(mn[to1[x]],mn[to2[x]]);low[x]=nm;return;}int getA(int x,int mnn){for(int i=16;i>=0;--i)if(mn[fa[x][i]]>=mnn)x=fa[x][i];return x;}int getB(int x,int mxx){for(int i=16;i>=0;--i)if(mx[fa[x][i]]<=mxx)x=fa[x][i];return x;} }A,B; struct Tree {#define ls son[x][0]#define rs son[x][1]int nm,s[N<<4],son[N<<4][2];int build(int l,int r){int x=++nm;if(l==r)return x;int mid=l+r>>1;ls=build(l,mid);rs=build(mid+1,r);return x;}int add(int lst,int l,int r,int y){int x=++nm;if(l==r){s[x]=1;return x;}int mid=l+r>>1;if(y<=mid){rs=son[lst][1];ls=add(son[lst][0],l,mid,y);}else{ls=son[lst][0];rs=add(son[lst][1],mid+1,r,y);}s[x]=s[ls]+s[rs];return x;}int ask(int x,int L,int R,int l,int r){if(L==l&&R==r)return s[x];int mid=L+R>>1;if(r<=mid)return ask(ls,L,mid,l,r);else if(l>mid)return ask(rs,mid+1,R,l,r);else return ask(ls,L,mid,l,mid)+ask(rs,mid+1,R,mid+1,r);} }T; int find(int x) {return f[x]==x?x:f[x]=find(f[x]); } void add(int x,int y) {e[++tot].to=y;e[tot].nx=h[x];h[x]=tot;return; } int main() {scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=m;++i){scanf("%d%d",&x,&y);x++;y++;add(x,y);add(y,x);}w=n;for(x=n;x>=1;--x){f[x]=x;for(int i=h[x];i;i=e[i].nx){int y=e[i].to;if(y<=x)continue;xx=find(x);yy=find(y);if(xx==yy)continue;A.to1[++w]=xx;A.to2[w]=yy;f[w]=w;f[xx]=w;f[yy]=w;}}w=n;for(x=1;x<=n;++x){f[x]=x;for(int i=h[x];i;i=e[i].nx){int y=e[i].to;if(y>=x)continue;xx=find(x);yy=find(y);if(xx==yy)continue;B.to1[++w]=xx;B.to2[w]=yy;f[w]=w;f[xx]=w;f[yy]=w;}}A.fa[2*n-1][0]=2*n-1;A.dfs(2*n-1);B.fa[2*n-1][0]=2*n-1;B.dfs(2*n-1);rt[0]=T.build(1,n);for(int i=1;i<=n;++i)v[A.dfn[i]]=B.dfn[i];for(int i=1;i<=n;++i)rt[i]=T.add(rt[i-1],1,n,v[i]);while(q--){scanf("%d%d%d%d",&s,&t,&l,&r);s++;t++;l++;r++;s=A.getA(s,l);//找到最高點t=B.getB(t,r);w=T.ask(rt[A.low[s]],1,n,B.dfn[t],B.low[t]);//前面一部分的點w-=T.ask(rt[A.dfn[s]-1],1,n,B.dfn[t],B.low[t]);if(w)puts("1");else puts("0");}return 0; }

總結(jié)

以上是生活随笔為你收集整理的【kruskal重构树】【主席树】werewolf 狼人(P4899)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。