题解 Fiend
让求的这个东西是什么呢?
考虑矩阵 \(A_{i, j}=[l_i\leqslant j\leqslant r_i]\)
这个矩阵的行列式为
\[\det=\sum\limits_p(-1)^k\prod p_i
\]
发现可以用这个东西的符号(以及是不是 0)来判断答案
那么要快速求这个矩阵的行列式
发现每一行中都有连续的一个区间是 1
考虑从小到大枚举 \(l\),在左端点是 \(l\) 的所有行中取 \(r\) 最小的,将其他行都消成 \([r+1, \cdots]\)
这样每一行都是一个连续的区间
这个过程需要可并堆,众所周知,最好写的左偏树是 pb_ds 左偏树
消完后每行都只剩下一个数,唯一对应了一个排列,直接计算逆序对数即可
那么复杂度 \(O(n\log n)\)
点击查看代码
#include <bits/stdc++.h>
#include <ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N], l[N], r[N];
namespace force{
int ans1, ans2;
void solve() {
ans1=ans2=0;
for (int i=1; i<=n; ++i) a[i]=i;
int cnt;
do {
for (int i=1; i<=n; ++i) if (a[i]<l[i]||a[i]>r[i]) goto jump;
cnt=0;
for (int i=1; i<=n; ++i)
for (int j=i+1; j<=n; ++j)
if (a[i]>a[j]) ++cnt;
++(cnt&1?ans1:ans2);
jump: ;
} while (next_permutation(a+1, a+n+1));
if (ans2>ans1) puts("Y");
else if (ans2<ans1) puts("F");
else puts("D");
}
}
namespace task1{
pair<ll, ll> f[1<<15];
void solve() {
memset(f, 0, sizeof(f));
f[0]={1, 0};
int lim=1<<n;
for (int s=0,pos; s<lim; ++s) {
pos=__builtin_popcount(s)+1;
for (int i=0; i<n; ++i) if (!(s&(1<<i)) && l[pos]<=i+1 && i+1<=r[pos]) {
int cnt=__builtin_popcount(s>>i);
if (cnt&1) f[s|(1<<i)].fir+=f[s].sec, f[s|(1<<i)].sec+=f[s].fir;
else f[s|(1<<i)].fir+=f[s].fir, f[s|(1<<i)].sec+=f[s].sec;
}
}
if (f[lim-1].fir>f[lim-1].sec) puts("Y");
else if (f[lim-1].fir<f[lim-1].sec) puts("F");
else puts("D");
}
}
namespace task{
int bit[N], p[N], ans;
inline void add(int i) {for (; i; i-=i&-i) ++bit[i];}
inline int query(int i) {int ans=0; for (; i<=n; i+=i&-i) ans+=bit[i]; return ans;}
struct cmp{inline bool operator () (pair<int, int> a, pair<int, int> b){return a>b;}};
__gnu_pbds::priority_queue<pair<int, int>, cmp, pairing_heap_tag> q[N];
void solve() {
ans=1;
memset(bit, 0, sizeof(bit));
for (int i=1; i<=n; ++i) q[i].clear();
for (int i=1; i<=n; ++i) q[l[i]].push({r[i], i});
for (int i=1; i<=n; ++i) {
// cout<<"i: "<<i<<endl;
if (!q[i].size()) {ans=0; break;}
int r=q[i].top().fir;
// cout<<"lr: "<<i<<' '<<r<<endl;
p[q[i].top().sec]=i;
q[i].pop();
if (q[i].size() && q[i].top().fir==r) ans=0;
q[r+1].join(q[i]);
}
for (int i=1; i<=n&&ans; ++i) ans*=(query(p[i])&1?-1:1), add(p[i]);
if (!ans) puts("D");
else if (ans>0) puts("Y");
else puts("F");
}
}
signed main()
{
freopen("fiend.in", "r", stdin);
freopen("fiend.out", "w", stdout);
int T=read();
while (T--) {
n=read();
for (int i=1; i<=n; ++i) l[i]=read(), r[i]=read();
// force::solve();
task::solve();
}
return 0;
}