Codeforces Round 1284 简要题解

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-<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值