您的位置:首页 > 其它

卿学姐与基本法(线段树+区间更新)

2016-05-01 16:26 405 查看


卿学姐与基本法


Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)


Submit 
Status

“做专题也要按照基本法”——蛤
离开了诡异的村庄,卿学姐来到了威廉·圣·乱七八糟王国,这里的国王咸鱼王是个智障。
国家涣散,盗贼四起,民不聊生。
见到这样的景象,卿学姐不禁潸然泪下,“悠悠苍天,奈何苦了苍生”。
自幼学习基本法的卿学姐决定向整个国家普及基本法,改善国家法度。
在这个国家总共有NN个人,每个人都有一个编号,编号从1开始。
由于整个国家的人实在是太多了,卿学姐每次只能对一个连续区间的编号的人普及基本法。
同时卿学姐还想知道在某个时刻某个区间还有多少人没有被普及基本法。


Input

第一行两个整数N,QN,Q,表示总共有NN个人,并且有QQ次事件。
接下来QQ行,每行三个整数t,L,Rt,L,R。如果tt是11,代表在这时,卿学姐向闭区间L,RL,R的人普及基本法。如果tt是22,代表在这时,卿学姐想知道闭区间L,RL,R里面有多少人还没有被普及基本法。
1≤N≤1000000001≤N≤100000000
1≤Q≤1000001≤Q≤100000
1≤t≤21≤t≤2
1≤L≤R≤N1≤L≤R≤N


Output

输出每个卿学姐想知道的答案


Sample input and output

Sample InputSample Output
5 3
1 1 2
1 4 5
2 2 4

1


Source

2016 UESTC Training for Data Structures

思路:
  这题一直WA,用了好多个线段树的姿势还是过不了第七个样例。之后看了看发下来的题解发现,根本就是一开始思路想错了,以后的实现就变得非常的
复杂,做了好几天也没能A掉。之后发现其实区间的更新都是固定了值的,所以与那些单点更新区间更新存在着很大的不同,所以我只要将要减去的值来做
就OK了,一开始只想到加,而没想到其实这道题目用减法更容易。



AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
using namespace std;
#define lson (rt<<1)
#define rson (rt<<1|1)
#define T 100000 + 50
#define inf 0x3f3f3f3f
typedef long long ll;

int n,m,x[(T<<2)],sz;
struct line
{
int f,L,R;
}le[T];

struct node
{
int L,R,mid;
int lazy,sum;
}tree[(T<<8)];

void Push_Up(int rt)
{
tree[rt].sum = tree[lson].sum + tree[rson].sum;
}

void Push_Down(int rt)
{
if(tree[rt].lazy){
tree[lson].sum = 0;
tree[rson].sum = 0;
tree[lson].lazy = 1;
tree[rson].lazy = 1;
tree[rt].lazy = 0;
}
}

void Build(int rt,int L,int R)//因为区间值已经全部确定了,所以全部赋值
{
tree[rt].L = L,tree[rt].R = R;
tree[rt].mid = (L+R)>>1;
tree[rt].lazy = tree[rt].sum = 0;
if(L==R){
tree[rt].sum = x[L]-x[L-1];//左闭右开区间的值
return;
}
Build(lson,L,tree[rt].mid);
Build(rson,tree[rt].mid+1,R);
Push_Up(rt);
}

void Update(int rt,int L,int R)//将符合的区间的值赋值为0
{
if(L<=tree[rt].L&&tree[rt].R<=R){
tree[rt].sum = 0;
tree[rt].lazy = 1;
return;
}
Push_Down(rt);
if(R<=tree[rt].mid){
Update(lson,L,R);
}
else if(L>tree[rt].mid){
Update(rson,L,R);
}
else {
Update(lson,L,tree[rt].mid);
Update(rson,tree[rt].mid+1,R);
}
Push_Up(rt);
}

int query(int rt,int L,int R)
{
if(L<=tree[rt].L&&tree[rt].R<=R){
return tree[rt].sum;
}
Push_Down(rt);
if(R<=tree[rt].mid){
return query(lson,L,R);
}
else if(L>tree[rt].mid){
return query(rson,L,R);
}
else {
return query(lson,L,tree[rt].mid)+query(rson,tree[rt].mid+1,R);
}
}

int main()
{
#ifdef zsc
freopen("input.txt","r",stdin);
#endif

int i,j,k;
while(~scanf("%d%d",&n,&m))
{
sz = 0;
for(i=0;i<m;++i){
scanf("%d%d%d",&le[i].f,&le[i].L,&le[i].R);
x[sz++] = le[i].L,x[sz++] = le[i].R;
//if(le[i].L!=1)x[sz++]=le[i].L-1;
x[sz++] = le[i].R+1;//为了使区间左边是闭合的
}
x[sz++] = n+1;//由于是左闭右开区间,所以要添加一个最大的值加一
sort(x,x+sz);
sz=unique(x,x+sz)-x;
Build(1,1,sz);
for(i=0;i<m;++i){
int L = lower_bound(x,x+sz,le[i].L)-x+1,
R = lower_bound(x,x+sz,le[i].R)-x+1;
if(le[i].f==1){
Update(1,L,R);
}
else {
printf("%d\n",query(1,L,R));
}
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树