【poj 2528】Mayor's posters 题意&题解&代码(C++)

来源:互联网 发布:c语言中与的符号 编辑:程序博客网 时间:2024/05/21 16:56

题目链接:
http://poj.org/problem?id=2528
题意:
n 个人依次贴海报,给出每张海报所贴的范围 li ,ri 求出最后还能看见多少张海报。
题解:
线段树,因为后来的海报总会覆盖之前张贴的海报,那么我们把操作从后往前枚举,用线段树 tr [ i ] . val 表示标号为 i 的节点所代表的区间中已经有多少个位置被覆盖。
然后就是简单的区间查询和区间修改。
然后看它的数据范围 10000000 直接线段树妥妥的MLE,需要用离散化,而且这个离散化还要注意一个细节,简单的排序后编号是不可以的,举一个例子:
3
1 10
1 4
6 10
直接排序后标号为

 vis[1]=1;vis[4]=2;vis[6]=3;vis[10]=4;

然后照这样的做法,先覆盖 3~4 在覆盖 1~2 ,然后覆盖 1~4 ,答案是 2 ,然而正确答案是 3 ,中间的位置5被神奇的跳过了,新的离散方法就是,离散时若发现 a[i] - a[i-1] > 1 那么 vis [ a[i] ] = vis [ a[i-1] ] + 2 ,这样的话就相当于给中间那些数留出来了一个空位,防止上面的情况发生,具体细节看代码。

代码:

#include<iostream>#include<algorithm>#include<stdio.h>#include<map>#define lson (id*2)#define rson (id*2+1)using namespace std;int ans;struct node{     int val;    int lazy;}tr[160005];void pushup(int id){    tr[id].val=tr[lson].val+tr[rson].val;}void pushdown(int id,int l,int r){    if (tr[id].lazy)    {        int mid=(l+r)/2;        tr[lson].val=mid-l+1;tr[lson].lazy=1;        tr[rson].val=r-mid;tr[rson].lazy=1;        tr[id].lazy=0;    }}void build(int id,int l,int r){    tr[id].lazy=0;    if (l>=r) {tr[id].val=0;return ;}    int mid=(l+r)/2;    build(lson,l,mid);    build(rson,mid+1,r);    pushup(id);    return ;}void add(int id,int l,int r,int L,int R,int v){    if (l>r || L>r || R<l) return ;    if (l>=L && r<=R) {tr[id].val=r-l+1;tr[id].lazy=1;return ;}    int mid=(l+r)/2;    pushdown(id,l,r);    if (L<=mid) add(lson,l,mid,L,R,v);    if (R>=mid+1) add(rson,mid+1,r,L,R,v);    pushup(id);}void query(int id,int l,int r,int L,int R){        if (l>r || L>r || R<l) return ;        if (l>=L && r<=R) {ans+=tr[id].val;return ;}        int mid=(l+r)/2;        pushdown(id,l,r);    if (L<=mid) query(lson,l,mid,L,R);        if (R>=mid+1) query(rson,mid+1,r,L,R);        pushup(id);}int zans,len,tot,T,n,m,l[10005],r[10005],a[20005];map<int,int>vis;int main(){    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        tot=0;len=0;zans=0;//      vis.clear();        for (int i=1;i<=n;i++)        {            scanf("%d%d",&l[i],&r[i]);            tot++;a[tot]=l[i];            tot++;a[tot]=r[i];            if (l[i]>r[i]) swap(l[i],r[i]);        }        sort(a+1,a+1+tot);        vis[a[1]]=1;        len=1;        for (int i=2;i<=tot;i++)        if (a[i]==a[i-1]) continue;        else if (a[i]-a[i-1]>1)        len+=2,vis[a[i]]=len;        else len++,vis[a[i]]=len;        //cout<<tr[1].val<<endl;        build(1,1,len);    //  for (int i=1;i<=len*4;i++)    /// tr[i].val=0,tr[i].lazy=0;        //cout<<tr[1].val<<endl;        for (int i=n;i>=1;i--)        {            ans=0;query(1,1,len,vis[l[i]],vis[r[i]]);            if (ans!=vis[r[i]]-vis[l[i]]+1)            zans++,add(1,1,len,vis[l[i]],vis[r[i]],1);            if (tr[1].val==len) break;        }        printf("%d\n",zans);    }   }
0 0