A. New Year and Naming
略
B. New Year and Ascent Sequence
略
C. New Year and Permutation
略
D. New Year and Conference
容易证明要判定是否存在venue-sensitive的非空子集,只需判定所有大小为 2 2 2的子集。也即判定是否存在区间 x ≠ y x\neq y x=y,使得 [ [ s a x , e a x ] ∩ [ s a y , e a y ] = ∅ ] ≠ [ [ s b x , s b x ] ∩ [ s b y , e b y ] = ∅ ] [[sa_x,ea_x]\cap[sa_y,ea_y]=\empty]\neq [[sb_x,sb_x]\cap[sb_y,eb_y]=\empty] [[sax,eax]∩[say,eay]=∅]=[[sbx,sbx]∩[sby,eby]=∅]。
比较简单的做法是考虑异或哈希,对每个区间附上一个随机权值,分别求出每个区间在 a a a和 b b b中与它不相交的区间集合的哈希值,判定是否相等。注意到对于一个区间 [ l 1 , r 1 ] [l_1,r_1] [l1,r1],区间 [ l 2 , r 2 ] [l_2,r_2] [l2,r2]与它不相交当且仅当 l 1 > r 2 l_1>r_2 l1>r2或 r 1 < l 2 r_1<l_2 r1<l2。那么可以分别对区间按端点排序后做几次two pointer求出哈希值。
时间复杂度为 O ( n log n ) \mathcal O(n\log n) O(nlogn)。
#include <bits/stdc++.h>
#include <random>
#define FR first
#define SE second
#define y1 yy
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pr;
mt19937 rnd(time(0));
ull randull() {
ull s=0;
for(int i=0;i<4;i++)
s=(s<<16)|((int)abs((int)rnd())%(1LL<<16));
return s;
}
ull s1[100005],s2[100005],num[100005];
pr a[100005],b[100005],c[100005],d[100005];
int main() {
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) {
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
a[i]=pr(x1,i);
b[i]=pr(y1,i);
c[i]=pr(x2,i);
d[i]=pr(y2,i);
num[i]=randull();
}
sort(a+1,a+n+1);
sort(b+1,b+n+1);
sort(c+1,c+n+1);
sort(d+1,d+n+1);
int r=0;
ull s=0;
for(int i=1;i<=n;i++) {
while (r<n&&b[r+1].FR<a[i].FR) {
r++;
s^=num[b[r].SE];
}
s1[a[i].SE]^=s;
}
int l=n+1;
s=0;
for(int i=n;i>0;i--) {
while (l>1&&a[l-1].FR>b[i].FR) {
l--;
s^=num[a[l].SE];
}
s1[b[i].SE]^=s;
}
r=0;
s=0;
for(int i=1;i<=n;i++) {
while (r<n&&d[r+1].FR<c[i].FR) {
r++;
s^=num[d[r].SE];
}
s2[c[i].SE]^=s;
}
l=n+1;
s=0;
for(int i=n;i>0;i--) {
while (l>1&&c[l-<