题目链接:2694: 发通知
题目分析:
给出n个同学,每个同学在一个时间段的愉悦度, [ L , R ] , W [L,R],W [L,R],W。由于,L,R值比较大,n的个数较小,进行离散化。然后,计算出每个时间点的同学个数和该点的愉悦度。这一步进行差分处理,对[L,R]这个范围进行+1操作和w的异或和。
注意:
- 对于异或这一点,异或就是不进位加法
异或运算符(^)
参加运算的两个数据,按二进制位进行“异或”运算。
运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0;
0^x = x, -x^x=0
即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。
运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0;
即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。
- 差分需要用到右端点+1,因此,直接对+1这个点进行离散,不然到后面再+1得到的就不是原来的点
- 数组要开到2倍N,不然点不够用(一个同学有L和R两个点)
代码如下:
代码一:用排序+去重处理离散化
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 5e5 + 10;
typedef long long LL;
int n,k;
struct Node{
int l,r;
int w;
};
vector<Node> query;
vector<int > nums;
LL s[N * 2];
int p[N * 2];
int find(int x){
return lower_bound(nums.begin(),nums.end(),x) - nums.begin() + 1;
}
int main(){
scanf("%d %d",&n,&k);
for(int i = 0; i < n; i ++ ){
int l,r,w;
scanf("%d %d %d",&l,&r,&w);
r += 1;
query.push_back({l,r,w});
nums.push_back(l);
nums.push_back(r);
}
sort(nums.begin(),nums.end());
nums.erase(unique(nums.begin(),nums.end()),nums.end());
for(auto t : query){
int l = find(t.l);
int r = find(t.r);
s[l] ^= t.w,s[r] ^= t.w;
p[l] += 1,p[r] -= 1;
}
for(int i = 1; i <= nums.size(); i ++ ){
p[i] += p[i - 1];
s[i] ^= s[i - 1];
}
LL ans = -1;
for(int i = 1; i <= nums.size(); i ++ ){
if(p[i] >= k){
ans = max(s[i],ans);
}
}
printf("%lld",ans);
return 0;
}
代码二:用 map+差分 处理
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int N = 5e5 + 10;
typedef long long LL;
int n,k;
map<LL,pair<LL,LL>> alls;
int main(){
scanf("%d %d",&n,&k);
for(int i = 0; i < n; i ++ ){
LL l,r,w;
scanf("%lld %lld %lld",&l,&r,&w);
alls[l].first += 1;
alls[r + 1].first -= 1;
alls[l].second ^= w;
alls[r + 1].second ^= w;
}
LL ans = -1,sum = 0,p = 0;
for(auto t : alls){
p += t.second.first;
sum ^= t.second.second;
if(p >= k) ans = max(ans,sum);
}
printf("%lld",ans);
return 0;
}