Fiend

来源:互联网 发布:立体照片制作软件 编辑:程序博客网 时间:2024/06/05 21:18

题目大意

满足li<=pi<=ri的排列p,问逆序对是奇数的多还是逆序对是偶数的多或者是否一样多?

解法

可以构造一个矩阵,ai,li~ri是1,然后就是问它行列式的符号或判断行列式是否为0。
模拟高斯消元,每次消到第i行时,让第i行变成第i列上有1且r最小的,这样可以保证任意时刻1都是一段区间。
可以用可并堆、平衡树或线段树来快速支持合并。

#include<cstdio>#include<algorithm>#include<set>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=100000+10,maxtot=maxn*100;struct dong{    int x,y;    friend bool operator <(dong a,dong b){        return a.y<b.y||a.y==b.y&&a.x<b.x;    }} a[maxn];int L[maxn],R[maxn],rank[maxn],sa[maxn];set<dong> s[maxn];int root[maxn],tree[maxtot],left[maxtot],right[maxtot];int fa[maxn];int i,j,k,l,t,n,m,ca,tot,top;int read(){    int x=0,f=1;    char ch=getchar();    while (ch<'0'||ch>'9'){        if (ch=='-') f=-1;        ch=getchar();    }    while (ch>='0'&&ch<='9'){        x=x*10+ch-'0';        ch=getchar();    }    return x*f;}int getfa(int x){    return fa[x]?fa[x]=getfa(fa[x]):x;}void change(int &x,int l,int r,int a,int b){    if (!x) x=++tot;    tree[x]+=b;    if (l==r) return;    int mid=(l+r)/2;    if (a<=mid) change(left[x],l,mid,a,b);else change(right[x],mid+1,r,a,b);}int query(int x,int l,int r){    if (l==r) return l;    int mid=(l+r)/2;    if (tree[left[x]]) return query(left[x],l,mid);else return query(right[x],mid+1,r);}int merge(int l,int r,int a,int b){    if (!a||!b) return a+b;    if (l==r){        tree[a]+=tree[b];        return a;    }    int mid=(l+r)/2;    left[a]=merge(l,mid,left[a],left[b]);    right[a]=merge(mid+1,r,right[a],right[b]);    tree[a]=tree[left[a]]+tree[right[a]];    return a;}void swa(int x,int y){    int k=getfa(L[x]);    change(root[k],1,n,rank[x],-1);    swap(L[x],L[y]);    swap(R[x],R[y]);    swap(rank[x],rank[y]);    swap(sa[rank[x]],sa[rank[y]]);    k=getfa(L[y]);    change(root[k],1,n,rank[y],1);}void move(int x,int y){    int a=getfa(x),b=getfa(y);    root[b]=merge(1,n,root[a],root[b]);    fa[a]=b;}int work(){    int t=1;    bool gjx;    fo(i,1,n) root[i]=fa[i]=0;    fo(i,1,tot) tree[i]=left[i]=right[i]=0;    tot=0;    fo(i,1,n){        change(root[L[i]],1,n,rank[i],1);    }    fo(i,1,n){        gjx=0;        k=getfa(i);        l=tree[root[k]];        while (l--){            j=query(root[k],1,n);            change(root[k],1,n,j,-1);            if (R[sa[j]]>=i){                gjx=1;                break;            }        }        if (!gjx) return 0;        j=sa[j];        if (j!=i){            t=-t;            swa(i,j);        }        move(i,R[i]+1);    }    return t;}int main(){    freopen("fiend.in","r",stdin);freopen("fiend.out","w",stdout);    ca=read();    while (ca--){        n=read();        fo(i,1,n) L[i]=read(),R[i]=read();        fo(i,1,n) a[i].x=i,a[i].y=R[i];        sort(a+1,a+n+1);        fo(i,1,n) rank[a[i].x]=i,sa[i]=a[i].x;        t=work();        if (t==0) printf("D\n");        else if (t>0) printf("Y\n");        else printf("F\n");    }}
原创粉丝点击