HDU 4325线段树+离散化(排序后去重)+lazy标记

来源:互联网 发布:itunes软件 编辑:程序博客网 时间:2024/05/17 09:05
这道题是我线段树入门的第一道题,搞了整整三天了!!!不过虽然智商有点低,学了整整三天了才会线段树、离散化法和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;}

原创粉丝点击