zoukankan      html  css  js  c++  java
  • POJ2528 Mayor's posters(区间替换&&线段切割)

    题目大意

    在墙上贴海报,海报可以相互覆盖,问最后能够看到多少种海报

    题解

    方法一:线段树

    嘛,就是区间染色问题,和POJ2777一样,不过颜色的种类比POJ2777多多了,最多有10000种。。。所以不能用位运算计算出颜色的总数量来。我们用另外一种方法,多了一个查询函数,在进行完海报的覆盖之后,对整个线段树进行一次查询,查询未清除的标记(碰到一个为标记的标记就回溯),未标记的种类总数就是最终可以看到的海报种类。WA了好多次。。。离散化的时候对位置进行排序的时候被坑了。。。我的离散化是有缺陷的。。。不过POJ数据太弱。。。居然AC了。。。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<bitset>
    #define MAXN 10005
    #define lson l,m,s<<1
    #define rson m+1,r,s<<1|1
    using namespace std;
    int setv[MAXN<<2];
    bool hash[MAXN<<2];
    int cnt;
    typedef struct {
        int p;
        int id;
    } NODE;
    NODE a[MAXN*2];
    bool cmp(NODE a,NODE b) {
        return a.p<b.p;
    }
    bool cmp2(NODE a,NODE b) {
        if(a.id==b.id)
            return a.p<b.p;
        return a.id<b.id;
    }
    void PushDown(int s) {
        if(setv[s]) {
            setv[s<<1]=setv[s<<1|1]=setv[s];
            setv[s]=0;
        }
    }
    void update(int ql,int qr,int l,int r,int s,int d ) {
        if(ql<=l&&r<=qr) {
            setv[s]=d;
            return;
        }
        PushDown(s);
        int m=(l+r)>>1;
        if(ql<=m) update(ql,qr,lson,d);
        if(qr>m) update(ql,qr,rson,d);
    }
    void query(int l,int r,int s) {
        if(setv[s]) {
            if(!hash[setv[s]]) {
                cnt++;
                hash[setv[s]]=true;
            }
            return;
        }
        if(l==r) return;
        int m=(l+r)>>1;
        query(lson);
        query(rson);
    }
    int main(void) {
        int n,T;
        cin>>T;
        while(T--) {
            scanf("%d",&n);
            for(int i=1; i<=n; i++) {
                scanf("%d%d",&a[2*i-1].p,&a[2*i].p);
                a[2*i-1].id=a[2*i].id=i;
            }
            sort(a+1,a+2*n+1,cmp);
            int pre=-1;
            int k=0;
            for(int i=1; i<=2*n; i++) {
                if(pre!=a[i].p) {
                    pre=a[i].p;
                    a[i].p=++k;
                } else
                    a[i].p=k;
            }
            sort(a+1,a+2*n+1,cmp2);
            memset(setv,0,sizeof(setv));
            for(int i=1; i<=n; i++)
                update(a[2*i-1].p,a[i*2].p,1,k,1,i);
            memset(hash,false,sizeof(hash));
            cnt=0;
            query(1,k,1);
            printf("%d\n",cnt);
          //  for(int i=1; i<=15; i++)
                //cout<<setv[i]<<endl;
        }
        return 0;
    }

    方法二:线段切割

    可以作为线段切割的模板题了。。。USACO3.1.4 Shaping Regions的一维形式,直接看代码吧。。应该很容易懂。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define MAXN 10005
    using namespace std;
    typedef struct {
        int l;
        int r;
    } NODE;
    NODE a[MAXN];
    bool f[MAXN];
    int n,ans;
    void cut(int l,int r,int col,int step) {
        while((step<n) &&(r<a[step].l||l>a[step].r)) step++;
        if(step>=n) {
            if(!f[col]) {
                ans++;
                f[col]=true;
            }
            return;
        }
        if(l<a[step].l) cut(l,a[step].l-1,col,step+1);
        if(a[step].r<r) cut(a[step].r+1,r,col,step+1);
    }
    int main(void) {
        int T;
        scanf("%d",&T);
        while(T--) {
            scanf("%d",&n);
            for(int i=0; i<n; i++)
                scanf("%d%d",&a[i].l,&a[i].r);
            memset(f,false,sizeof(f));
            ans=1;
            f[n-1]=true;
            for(int i=n-2; i>=0; i--)
                cut(a[i].l,a[i].r,i,i+1);
            printf("%d\n",ans);
        }
        return 0;
    }

    方法一用了94ms,方法二用了250ms,不过用线段切割做代码相当的简洁

  • 相关阅读:
    python super()函数
    java中的方法
    python的5大数据类型操作之列表篇
    java流程控制
    eval函数 exec函数 compile函数之间的应用
    基础语法
    java中对字符串的操作
    iOS 简单的文件写入
    iOS弹出窗口
    iOS block传值和属性传值
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3079974.html
Copyright © 2011-2022 走看看