BZOJ3526 [Poi2014]Card 【线段树】

题目链接

BZOJ3526

题解

思来想去,发现很显然可以用线段树维护
每个区间保存所有合法方案的左右端点【当左端点一定是,右端点当然存最小的那个就行了】

这么整的数,\(\frac{1}{1000}\)的概率啊23333

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
#define ls (u << 1)
#define rs (u << 1 | 1)
using namespace std;
const int maxn = 200005,maxm = 100005,INF = 1000000000;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    return out * flag;
}
int ln[maxn << 2][2],rn[maxn << 2][2],cnt[maxn << 2];
int a[maxn],b[maxn],n,m;
void upd(int u){
    if (!cnt[ls] || !cnt[rs]) cnt[u] = 0;
    else {
        cnt[u] = 0;
        for (int i = 0; i < cnt[ls]; i++){
            int r = INF;
            for (int j = 0; j < cnt[rs]; j++){
                if (rn[ls][i] <= ln[rs][j])
                    r = min(r,rn[rs][j]);
            }
            if (r < INF){
                ln[u][cnt[u]] = ln[ls][i];
                rn[u][cnt[u]] = r;
                cnt[u]++;
            }
        }
    }
}
void build(int u,int l,int r){
    if (l == r){
        cnt[u] = 2;
        ln[u][0] = rn[u][0] = a[l];
        ln[u][1] = rn[u][1] = b[l];
        return;
    }
    int mid = l + r >> 1;
    build(ls,l,mid);
    build(rs,mid + 1,r);
    upd(u);
}
void modify(int u,int l,int r,int pos,cp v){
    if (l == r){
        cnt[u] = 2;
        ln[u][0] = rn[u][0] = v.first;
        ln[u][1] = rn[u][1] = v.second;
        return;
    }
    int mid = l + r >> 1;
    if (mid >= pos) modify(ls,l,mid,pos,v);
    else modify(rs,mid + 1,r,pos,v);
    upd(u);
}
void print(int u,int l,int r){
    if (l == r){
        printf("(%d,%d)  ",ln[u][0],ln[u][1]);
        return;
    }
    int mid = l + r >> 1;
    print(ls,l,mid); print(rs,mid + 1,r);
}
int main(){
    n = read();
    REP(i,n) a[i] = read(),b[i] = read();
    build(1,1,n);
    m = read();
    int c,d;
    while (m--){
        //print(1,1,n); puts("");
        c = read(); d = read();
        modify(1,1,n,c,mp(a[d],b[d]));
        modify(1,1,n,d,mp(a[c],b[c]));
        swap(a[c],a[d]); swap(b[c],b[d]);
        puts(cnt[1] ? "TAK" : "NIE");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Mychael/p/9098580.html