[随机 Hash] Codeforces 799F Round #413 F. Beautiful fountains rows

就是给题目中给出的每个区间随一个值 然后判断一个区间是否合法 把区间内所有数xor和 再xor上 区间中出现过的所有数的xor和 为 0
前缀和统计下
本人脸黑 单hash交了好几发都是WA 迫不得已双hash

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<ctime>
#define pb push_back 
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<ull,ull> abcd;

inline ll sum(ll n){ return n*(n+1)/2;}
inline ll sum2(ll n){ return n*(n+1)*(2*n+1)/6;}
inline ll calc(ll n){ return (n+1)*sum(n)-sum2(n);}

const int N=200005;

#define read(x) scanf("%d",&(x))

int n,m;
int l[N],r[N];
vector<int> L[N],R[N];
ull h1[N],h2[N],a[N],b[N];
map<abcd,ll> F,G;
ll ans;
int cnt[N];

int main(){
  srand(time(0));
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(n); read(m);
  for (int i=1;i<=n;i++){
    read(l[i]); read(r[i]);
    L[l[i]].pb(i); R[r[i]].pb(i);
    a[i]=(ull)rand()*rand()*rand()*rand()*rand();
    b[i]=(ull)rand()*rand()*rand()*rand()*rand();
    h1[l[i]]^=a[i]; h1[r[i]+1]^=a[i];
    h2[l[i]]^=b[i]; h2[r[i]+1]^=b[i];
    cnt[l[i]]++; cnt[r[i]+1]--;
  }
  for (int i=1;i<=m;i++) h1[i]^=h1[i-1],h2[i]^=h2[i-1];
  for (int i=1;i<=m;i++) h1[i]^=h1[i-1],h2[i]^=h2[i-1];
  G[abcd(0,0)]++; F[abcd(0,0)]=0;
  ull s1=0,s2=0,t1=0,t2=0;
  for (int i=1;i<=m;i++){
    for (int x:L[i]) s1^=a[x],s2^=b[x];
    ans+=G[abcd(s1^h1[i],s2^h2[i])]*i-F[abcd(s1^h1[i],s2^h2[i])];
    for (int x:R[i]) t1^=a[x],t2^=b[x];
    F[abcd(t1^h1[i],t2^h2[i])]+=i; G[abcd(t1^h1[i],t2^h2[i])]++;
  }
  for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
  for (int i=1;i<=m;)
    if (cnt[i]==0){
      int j=i; while (j+1<=m && cnt[j+1]==0) j++;
      ans-=calc(j-i+1);
      i=j+1;
    }else
      i++;
  printf("%I64d\n",ans);
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值