Peaks加强版 黑暗爆炸 - 3551 Kruskal重构树 + 主席树
生活随笔
收集整理的這篇文章主要介紹了
Peaks加强版 黑暗爆炸 - 3551 Kruskal重构树 + 主席树
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
文章目錄
- 題意:
- 思路:
題意:
給你一張圖,有nnn個山峰,每個山峰高度為hih_ihi?,有mmm條邊,每條邊有個難度值wiw_iwi?,現在有qqq個詢問,每次詢問給定一個山峰vvv,問從這個山峰開始走,經過難度不超過xxx的路徑能走到的山峰中,第kkk大的山峰高度是多少。
n≤1e5,m,q≤5e5,hi,wi<=1e9n\le1e5,m,q\le5e5,h_i,w_i<=1e9n≤1e5,m,q≤5e5,hi?,wi?<=1e9
思路:
KruskalKruskalKruskal重構樹維護連通性經典題啦,把邊從小到大排序,讓后建重構樹,這樣每兩個點之間的最大路徑是他們的lcalcalca的點權,那么我們從vvv這個點往上跳,一直跳到深度最小的且valf≤xval_f\le xvalf?≤x的點,讓后這顆子樹中所有葉子節點就是能到的山峰,找第kkk大的問題當然是留給主席樹解決啦,按照dfsdfsdfs序建主席樹,查詢第kkk大就好了。
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") //#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<map> #include<cmath> #include<cctype> #include<vector> #include<set> #include<queue> #include<algorithm> #include<sstream> #include<ctime> #include<cstdlib> #define X first #define Y second #define L (u<<1) #define R (u<<1|1) #define pb push_back #define mk make_pair #define Mid (tr[u].l+tr[u].r>>1) #define Len(u) (tr[u].r-tr[u].l+1) #define random(a,b) ((a)+rand()%((b)-(a)+1)) #define db puts("---") using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } //void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } //void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII;const int N=200010,mod=1e9+7,INF=0x3f3f3f3f; const double eps=1e-6;int n,m,q; int a[N],p[N],fa[N][22],in[N],ed[N],se[N],tot; int root[N],idx,h[N]; vector<int>v[N],li; struct Edge {int a,b,w;bool operator < (const Edge &W) const{return w<W.w;} }edge[N*3]; struct Node {int l,r;int cnt; }tr[N*40];int find(int x) {return x==p[x]? x:p[x]=find(p[x]); }int get(int x) {return lower_bound(li.begin(),li.end(),x)-li.begin(); }void insert(int p,int &q,int l,int r,int pos) {q=++idx; tr[q]=tr[p];tr[q].cnt++;if(l==r) return;int mid=(l+r)>>1;if(pos<=mid) insert(tr[p].l,tr[q].l,l,mid,pos);else insert(tr[p].r,tr[q].r,mid+1,r,pos); }int query(int p,int q,int l,int r,int k) {if(l==r) return li[l];int mid=(l+r)>>1,cnt=tr[tr[q].l].cnt-tr[tr[p].l].cnt;if(k<=cnt) return query(tr[p].l,tr[q].l,l,mid,k);else return query(tr[p].r,tr[q].r,mid+1,r,k-cnt); }void dfs(int u,int f) {se[u]=1;in[u]=++tot; fa[u][0]=f;for(int i=1;i<=19;i++) fa[u][i]=fa[fa[u][i-1]][i-1];if(u<=n) insert(root[tot-1],root[tot],0,li.size()-1,get(a[u]));else root[tot]=root[tot-1];for(auto x:v[u]) if(x!=f) dfs(x,u),se[u]+=se[x];ed[u]=tot; }int main() { // ios::sync_with_stdio(false); // cin.tie(0);scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=n;i++) scanf("%d",&a[i]),li.pb(a[i]);sort(li.begin(),li.end()); li.erase(unique(li.begin(),li.end()),li.end());for(int i=1;i<=n*2;i++) p[i]=i;for(int i=1;i<=m;i++){int a,b,w; scanf("%d%d%d",&a,&b,&w);edge[i]={a,b,w};}sort(edge+1,edge+1+m);for(int i=1,tot=n;i<=m;i++){int aa=edge[i].a,b=edge[i].b,w=edge[i].w;int pa=find(aa),pb=find(b);if(pa==pb) continue;tot++; p[pa]=tot; p[pb]=tot;v[tot].pb(pa); v[tot].pb(pb);a[tot]=w;if(tot==n*2-1) break;//cout<<pa<<' '<<pb<<' '<<tot<<' '<<w<<endl;}a[0]=INF;for(int i=1;i<=n*2-1;i++) if(i==find(i)) dfs(i,0);int ans=0;while(q--){int v,x,k; scanf("%d%d%d",&v,&x,&k);v^=ans; x^=ans; k^=ans; for(int i=19;i>=0;i--) if(a[fa[v][i]]<=x) v=fa[v][i];int sum=tr[root[ed[v]]].cnt-tr[root[in[v]-1]].cnt;if(k>sum) ans=-1;else ans=query(root[in[v]-1],root[ed[v]],0,li.size()-1,sum-k+1);printf("%d\n",ans);ans=ans==-1? 0:ans;}return 0; } /**/總結
以上是生活随笔為你收集整理的Peaks加强版 黑暗爆炸 - 3551 Kruskal重构树 + 主席树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 台湾医院全员大跳抖肩舞火遍网络台湾医院抖
- 下一篇: 电脑三大外接显示屏连接口电脑显示屏三个接