【線段樹分治MOBAN】 LUOGU5787
阿新 • • 發佈:2021-11-03
一道線段樹分治模板題。
https://www.luogu.com.cn/problem/P5787
線段樹分治用於解決在時間上插入的離線處理方法。具體將時間軸建立為一棵線段樹,一個操作對時間軸的影響插入logn段線段樹中,最後遍歷線段樹到時間路徑上進行操作。相對於CDQ分治,此時詢問被看做是一個時間點。
就挺棒的,該題就參照NOIP2010關押罪犯那麼搞來判斷二分圖,每個點拆分為x和x+n(x與它的敵人),當x與y連邊,則相當於x與y+N連邊,y與x+n連邊(敵人的敵人就是朋友),當然,如果x與x+n連邊了則證明不是二分圖。
實現上由於線段樹的撤銷操作,並查集不路徑壓縮,按秩合併即可。
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5+5; int n; int a[maxn]; char ss[maxn]; int b[maxn],r[maxn]; int bl,rl; void sol() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; bl = rl = 0; scanf("%s",&ss[1]); for(int i=1;i<=n;i++) { if(ss[i]=='B') b[++bl] = a[i]; else r[++rl] = a[i]; } sort(b+1,b+1+bl); sort(r+1,r+1+rl,greater<int>()); bool flag = 1; for(int i=1;i<=bl;i++) { if(b[i]<i) flag = 0; } for(int i=1;i<=rl;i++) { if(r[i]>(n-i+1)) flag = 0; } if(flag) puts("YES"); else puts("NO"); } int main(){ int t; cin>>t; while(t--) sol(); return 0; }