【线段树分治MOBAN】 LUOGU5787

一道线段树分治模板题。


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;
}
posted @ 2021-11-03 13:02  Newuser233  阅读(38)  评论(0编辑  收藏  举报