题目大意
满足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");
}
}