CF799F Beautiful fountains rows

找到这道题的时候,我啪的一下啊!很快啊!我想到了暴力将每个数搞到集合里的做法,然后每个集合有一个实际序列 [li,ri]

但这样就被偷袭了!

考虑只需要集合整个的权值,我们直接开个差分数组搞下就好了。然后长度和就往块内 hash 顺便记个集合下标。

 这题不同于这题的原因是这题的区间是连续的。所以可以不用分块维护。

那么,显然我们要维护异或前缀和及区间出现过的数的异或前缀和。

但既然区间是连续的,假如这段区间长度偶数,那么异或起来为 0,又因为 0 肯定比较好判断,所以我们可以让这段区间的长度 1

即修改作用在 [x+1,y],假如查询 [x,y] ,那么相当于查询 [x+1,y] 的异或和是否为 0

那么为什么 loj 那题不能这样做的,主要原因还是因为颜色不连续,我认为。

这题中对于空集的话可以最后在减去贡献。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <ctime>
 
#define ll long long
#define ull unsigned ll
using namespace std;
int rd() {
    int f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}
ll lrd() {
    ll f=1,sum=0; char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return sum*f;
}
const int N=(int)(2e5+5);
map<ull,pair<int,ull> >mp;
ull ans,cnt[N],s[N],nmsl[N];
int n,m;
 
ull get_rand() {
    return 1llu*RAND_MAX*RAND_MAX*RAND_MAX*rand()+1llu*RAND_MAX*rand()+1llu*rand()*rand()+1llu*RAND_MAX*rand()+1llu*rand();
}
 
signed main() {
    srand(time(NULL)*114);
    int x,y;
    n=rd(); m=rd();
    for(int i=1;i<=n;i++) {
        x=rd(); y=rd();
        ++cnt[x]; --cnt[y+1];
        ull qwq=get_rand();
        s[x+1]^=qwq; s[y+1]^=qwq;
    }
    for(int i=1;i<=m;i++) s[i]^=s[i-1];
    for(int i=1;i<=m;i++) s[i]^=s[i-1];
    for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
    for(int i=1;i<=m;i++) {
        pair<int,ull>qwq=mp[s[i]];
        qwq.first++; qwq.second+=i-1; mp[s[i]]=qwq;
        ans+=1llu*qwq.first*i-qwq.second;
    }
     
    for(int i=1;i<=m;i++) {
        if(!cnt[i]) nmsl[i]=nmsl[i-1]+1;
        else nmsl[i]=0;
    }
    for(int i=1;i<=m;i++) ans-=nmsl[i]*(nmsl[i]+1)/2;
    cout<<ans;
}

  


__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/15156415.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(141)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示