这道题是我线段树入门的第一道题,搞了整整三天了!!!不过虽然智商有点低,学了整整三天了才会线段树、离散化法和lazy标记法,不过还是值了,把这线段树搞定了就好,多做几道题巩固一下……如果不知道lazy标记看前一章,或者百度看别人的解释!
#include <iostream>
#include <map>
#include <deque>
#include <vector>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
int INF=1<<30;
const int M=100005;
struct node
{
int a,b,sum,lazy;
}tree[M*3];
void build(int i,int a,int b)
{
tree[i].a=a;
tree[i].b=b;
tree[i].sum=0;
tree[i].lazy=0;
//printf("tree[%d].a=%d tree[%d].b=%d tree[%d].sum=%d\n",i,tree[i].a,i,tree[i].b,i,tree[i].sum);
if(a==b) return;
int mid=(a+b)>>1;
build(i*2,a,mid);
build(i*2+1,mid+1,b);
}
void update(int i,int a,int b,int val)
{
if(tree[i].a==a&&tree[i].b==b)
{
tree[i].sum+=val; //刚开始我是tree[i].sum++,提交错了,后面才记得,lazy标记的时候可能超过1了,所以加val就得了。看到别人是tree[i].sum+=(b-a+1)*val,其实这有点难理解,我们要的结果只是最后一个结点而已嘛,其他的结点你管他算成什么呢,只要tree[i].a==tree[i].b的那个结点算对就行了,因为最后一点,b-a+1==1,所以直接加上val就得啦!!!因为这个,让我又理解了好久才知道别人写的这个是什么意思,真是滴!!!
tree[i].lazy+=val;
//printf("tree[%d].a=%d tree[%d].b=%d tree[%d].sum=%d\n",i,tree[i].a,i,tree[i].b,i,tree[i].sum);
return;
}
int mid=(tree[i].a+tree[i].b)/2;
if(tree[i].lazy!=0)
{
update(i*2,tree[i].a,mid,tree[i].lazy);
update(i*2+1,mid+1,tree[i].b,tree[i].lazy);
tree[i].lazy=0;
}
if(a<=mid) update(i*2,a,min(mid,b),val);
if(b>mid) update(i*2+1,max(a,mid+1),b,val);
}
int query(int i,int x)
{
int mid=(tree[i].a+tree[i].b)>>1;
if(tree[i].a==x&&tree[i].b==x) return tree[i].sum;
if(tree[i].lazy!=0)
{
update(i*2,tree[i].a,mid,tree[i].lazy);
update(i*2+1,mid+1,tree[i].b,tree[i].lazy);
tree[i].lazy=0;
}
if(x<=mid) return query(i*2,x);
else return query(i*2+1,x);
}
int main()
{
int t,k=1;
scanf("%d",&t);
while(t--)
{
map<int,int>q;
int p[M],w[M],j=0,n,m,i,c[M],d[M];
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d%d",&c[i],&d[i]);
w[j++]=c[i];
w[j++]=d[i];
}
for(i=0;i<m;i++)
{
scanf("%d",&p[i]);
w[j++]=p[i];
}
printf("Case #%d:\n",k++);
sort(w,w+j); //因为排序了才可以用去重函数
int ans=unique(w,w+j)-w; //去重
build(1,1,ans); //建平衡二叉树
for(i=0;i<ans;i++)
q[w[i]]=i+1; //离散化,即压缩
for(i=0;i<n;i++)
update(1,q[c[i]],q[d[i]],1); //更新线段树
for(i=0;i<m;i++)
printf("%d\n",query(1,q[p[i]])); //查询输出
}
return 0;
}