AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 20005;//不晓得为什么写成100005就过不了
struct node{
int l,r;
int c;
}tree[N<<2];
int l[N],r[N];
int record[N];
int ans;
struct Line{
int point;//记录端点做点
int num;//记录原来的编号
bool operator < (const Line &a)const{
return point < a.point;
}
}line[N<<1];
void build(int id,int l,int r){
tree[id].l = l;
tree[id].r = r;
tree[id].c = 0;
if(l == r){
return ;
}
int mid = (l+r)>>1;
build(id<<1,l,mid);
build((id<<1)|1,mid+1,r);
}
void pushdown(int id){
if(tree[id].c){
tree[id<<1].c = tree[id].c;
tree[(id<<1)|1].c = tree[id].c;
tree[id].c = 0;
}
}
void update(int id,int l,int r,int val){
if(tree[id].l >= l && tree[id].r <= r){
tree[id].c = val;
return ;
}
pushdown(id);
int mid = (tree[id].l+tree[id].r)>>1;
if(l <= mid)
update(id<<1,l,r,val);
if(mid < r)
update((id<<1)|1,l,r,val);
}
void query(int id){
if(tree[id].c){
if(!record[tree[id].c]){
ans++;
record[tree[id].c] = 1;
}
return ;
}
query(id<<1);
query((id<<1)|1);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
for(int i = 0; i < n; i++){
scanf("%d%d",&l[i],&r[i]);
line[i<<1].point = l[i];//记录数据用于离散化
line[(i<<1)|1].point = r[i];
line[i<<1].num = -(i+1);//线段第一个端点用负数记录
line[(i<<1)|1].num = i+1;//线段第二个端点用正数记录
}
sort(line,line+2*n);
int tmp = line[0].point;
int cnt = 1;
for(int i = 0; i < n*2; i++){
if(tmp != line[i].point){ //如果当前端点和前面的端点不一样,编号值+1
cnt++;
tmp = line[i].point;
}
if(line[i].num < 0)
l[-line[i].num-1] = cnt;
else
r[line[i].num-1] = cnt;
}
build(1,1,cnt);
for(int i = 0; i < n; i++)
update(1,l[i],r[i],i+1);
memset(record,0,sizeof(record));
ans = 0;
query(1);
printf("%d\n",ans);
}
}
本文介绍了一种使用线段树进行区间更新和查询的方法,适用于处理大量区间修改与查询操作的问题。通过离散化处理端点坐标,利用递归方式建立线段树,并实现了区间覆盖更新及查询统计功能。
676

被折叠的 条评论
为什么被折叠?



