1. 程式人生 > >cogs1682. [HAOI2014]貼海報 x

cogs1682. [HAOI2014]貼海報 x

math cst ima n) esp style 現在 amp cto

1682. [HAOI2014]貼海報

★★☆ 輸入文件:ha14d.in 輸出文件:ha14d.out 簡單對比
時間限制:1 s 內存限制:256 MB

【題目描述】

Bytetown城市要進行市長競選,所有的選民可以暢所欲言地對競選市長的候選人發表言論。為了統一管理,城市委員會為選民準備了一個張貼海報的electoral墻。

張貼規則如下:

1.electoral墻是一個長度為N個單位的長方形,每個單位記為一個格子;

2.所有張貼的海報的高度必須與electoral墻的高度一致的;

3.每張海報以“A B”表示,即從第A個格子到第B個格子張貼海報;

4.後貼的海報可以覆蓋前面已貼的海報或部分海報。

現在請你判斷,張貼完所有海報後,在electoral墻上還可以看見多少張海報。

【輸入格式】

第一行: N M 分別表示electoral墻的長度和海報個數

接下來M行: Ai Bi 表示每張海報張貼的位置

【輸出格式】

輸出貼完所有海報後,在electoral墻上還可以看見的海報數。

【樣例輸入】

100 5

1 4

2 6

8 10

3 4

7 10

【樣例輸出】

4

【提示】

技術分享

【約束條件】

1 0<= N <= 10000000 1<=M<=1000 1<= Ai <= Bi <=10000000

所有的數據都是整數。數據之間有一個空格

思路:

  1)首先這道題暴力可以拿80分!(在luogu上可以AC!!!!)

  2)然後考場上作死寫了個並查集。。。61分

  3)正解:

      ①線段樹(然而我沒寫~)

      ②浮水法

坑點:

  因為給出的是所位於的塊,不是左右端點,所以在處理浮水法的時候記得要右端點+1,或者左端點-1

上代碼:

1)暴力

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string
> #include <cstdio> using namespace std; const int M = 1e7 + 1; int n,m,l,r,ans; int a[M],v[M]; inline int reads() { int x=0,f=1;char ch=getchar(); while(ch<0 || ch>9) {if(ch==-) f=-1;ch=getchar();} while(ch>=0 && ch<=9) {x=10*x+ch-0;ch=getchar();} return x*f; } int main() { freopen("ha14d.in","r",stdin); freopen("ha14d.out","w",stdout); n=reads(),m=reads(); for(int i=1;i<=m;i++) { l=reads(),r=reads(); if(r<l) swap(l,r); for(int j=l;j<=r;j++) a[j]=i; } for(int i=1;i<=n;i++) { if(!v[a[i]] && a[i]) { ans++; v[a[i]]=1; } } printf("%d",ans); return 0; }

2)作死並查集

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
 
using namespace std;
 
inline int reads()
{
    int x=0,f=1;char ch=getchar();
    while(ch<0 || ch>9)
    {if(ch==-) f=-1;ch=getchar();}
    while(ch>=0 && ch<=9)
    {x=10*x+ch-0;ch=getchar();}
    return x*f;
}
 
const int M = 1e7 + 2333333;                ///多開幾個 
const int N = 1111;
int n,m;
int f[M];
int ans[M],anse;
int Ls[N],Rs[N];
 
int getf(int x)
{return f[x] == x ? x : f[x] = getf(f[x]);}
 
int main()
{
    freopen("ha14d.in","r",stdin);
    freopen("ha14d.out","w",stdout);
    n=reads();m=reads();                    ///n是n塊,不是左右端點!!! 
    for(int i=1;i<=n+2;i++)
        f[i]=i;
    for(int i=1;i<=m;i++)                   ///m組數據 
    {                                       ///手動從1開始,從0不會... 
        Ls[i]=reads();
        Rs[i]=reads()+1;                    ///因為給出不是點的坐標,是塊的坐標 
    }
    int l,r; 
    for(int i=m;i>=1;i--)                   ///逆序張貼,因為只需要的是最後的能看到的海報 
    {
        l=Ls[i],r=Rs[i];                    ///左右端點 
        if(l>r) swap(l,r);                  ///maybe?會出現"left">"right"的情況(考慮最壞情況,以防萬一,以前做過一個題就是惡心的數據!) 
        for(int j=getf(l);j<=r;j=getf(j+1))
        {
            f[getf(j)]=getf(j+1);           ///將當前被張貼報紙的父結點手動設置到最後一個的父結點 
///            ans[j]=i;
            ans[i]++; 
            if(getf(1)==n+2) break;         ///表示已經貼完 
        }
    }
 
    for(int i=1;i<=n+1;i++)
    {
///        printf("%d=%d\n",i,ans[i]);      ///輸出調試??? 
        if(ans[i]) anse++;
    }
    printf("%d\n",anse);
 
    return 0;
}

3)正解(浮水法)

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
 
const int M = 1001;
int n,m,ans=1;
bool v[M];
 
struct U {
    int l,r,id;
    //id 為第幾張海報 
}t[M];
 
inline int reads()
{
    int x=0,f=1;char ch=getchar();
    while(ch<0 || ch>9)
    {if(ch==-) f=-1;ch=getchar();}
    while(ch>=0 && ch<=9)
    {x=10*x+ch-0;ch=getchar();}
    return x*f;
}
 
void swim(int ql,int qr,int nowid,int preid)
{
    if(v[preid])
        return;
    while(nowid<=m && (qr<=t[nowid].l || ql>=t[nowid].r))
        nowid++;
    if(nowid>m)
    {
        v[preid]=true;
        ans++;
        return;
    }
    if(ql<t[nowid].l && qr>t[nowid].l)
        swim(ql,t[nowid].l,nowid+1,preid);
    if(ql<t[nowid].r && qr>t[nowid].r)
        swim(t[nowid].r,qr,nowid+1,preid);
}
 
int main()
{
    freopen("ha14d.in","r",stdin);
    freopen("ha14d.out","w",stdout);
    n=reads();m=reads();
    for(int i=1;i<=m;i++)
    {
        t[i].l=reads(),t[i].r=reads()+1;
        t[i].id=i;
    }
    for(int i=m-1;i>=1;i--)
        swim(t[i].l,t[i].r,i+1,i);
    printf("%d",ans);
    return 0;
}

cogs1682. [HAOI2014]貼海報 x