B - 卿学姐与基本法
Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
“做专题也要按照基本法”——蛤
离开了诡异的村庄,卿学姐来到了威廉·圣·乱七八糟王国,这里的国王咸鱼王是个智障。
国家涣散,盗贼四起,民不聊生。
见到这样的景象,卿学姐不禁潸然泪下,“悠悠苍天,奈何苦了苍生”。
自幼学习基本法的卿学姐决定向整个国家普及基本法,改善国家法度。
在这个国家总共有 N 个人,每个人都有一个编号,编号从1开始。
由于整个国家的人实在是太多了,卿学姐每次只能对一个连续区间的编号的人普及基本法。
同时卿学姐还想知道在某个时刻某个区间还有多少人没有被普及基本法。
Input
第一行两个整数 N,Q N,Q,表示总共有 N N个人,并且有 Q Q次事件。
接下来 Q Q行,每行三个整数 t,L,R t,L,R。如果 t t是 1 1,代表在这时,卿学姐向闭区间 L,R L,R的人普及基本法。如果 t t是 2 2,代表在这时,卿学姐想知道闭区间 L,R L,R里面有多少人还没有被普及基本法。
1≤N≤100000000
1≤Q≤100000
1≤t≤2
1≤L≤R≤N
Output
输出每个卿学姐想知道的答案
Sample input and output
Sample Input | Sample Output |
---|---|
5 3 1 1 2 1 4 5 2 2 4 | 1 |
Source
2016 UESTC Training for Data Structures Problem B
My Solution
对很多个区间进行处理,
这里建一个结构体放存放区间,然后把区间放到vector里,根据左边界排序,
然后逐次进行处理使所以区间变成不相交的区间
一直维护这样的区间
至于说像堆, 是因为:
这个也是延迟操作,在查询单时候才进行维护的
维护时,删除vector的那些元素时令那个元素的 了left 成员为INF,然后sort再pop_back()
查询的时候就vector中的元素一个个查询过去了☺
复杂度 不会算,感觉不是很暴力
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxq = 100000 +8;
const int INF = 0x3f3f3f3f;
struct interval{
int l,r;
interval(int x, int y) : l(x), r(y) {}
};
vector<interval> val;
bool cmp(const interval& a, const interval& b)
{
return a.l < b.l;
}
int main()
{
#ifdef LOCAL
freopen("a.txt", "r", stdin);
#endif // LOCAL
int N, Q;
scanf("%d%d", &N, &Q);
int t, L, R, sz, ans;
while(Q--){
scanf("%d%d%d", &t, &L, &R);
if(t == 1) {
val.push_back(interval(L, R));
sort(val.begin(), val.end(), cmp);
sz = val.size();
for(int i = 0; i < sz; i++){
if(i != sz-1 && val[i].l == val[i+1].l) {val[i].l = INF; val[i+1].r = max(val[i].r, val[i+1].r);}
else if(i != sz-1 && val[i].r >= val[i+1].l) {
val[i+1].l = val[i].l; val[i].l = INF; val[i+1].r = max(val[i].r, val[i+1].r);
}
}
sort(val.begin(), val.end(), cmp);
while(val[sz-1].l == INF){
val.pop_back();
sz--;
}
}
else{
sz = val.size();ans = R - L + 1;
for(int i = 0; i < sz; i++){
if(val[i].l <= L && val[i].r >= R) {ans = 0; break;}
else if(val[i].l >= L && val[i].r <= R) {ans -= (val[i].r - val[i].l +1);} // 里面,左闭右开
else if(val[i].l >= L && val[i].l <= R && val[i].r >= R) {ans -= (R - val[i].l +1);}
else if(val[i].l <= L && val[i].r >= L && val[i].r <= R) {ans -= (val[i].r - L +1);}
}
printf("%d\n", ans);
}
}
return 0;
}
据说也可以用线段树^_^
Thank you!
------from ProLights