2528:市長のポスター:なぜセグメントの木?なぜ離散?記事のタイトルを知ろう

効果の対象に

我慢できないアブダビ(Bytetown)市民は、市長候補の選挙運動は喜んで国の選挙ポスターを入れてきました。市議会は最終的に場所の選挙ポスターに壁を建設することを決定し、そして次のルールの導入:

各候補者は、壁にポスターを置くことができます。

すべてのポスター壁の高さは、高さに等しい、ポスターの幅は、バイトの任意の整数(町のバイトのバイト長)であってもよいです。

なお、壁部、1バイトの幅の各部分を複数に分割されています。

各ポスターは完全に、より連続壁セグメントをカバーしなければなりません。

彼らは(すべての候補者を収容するのに十分なスペースを持つために)長い壁バイト千万の壁を構築しました。キャンペーンが再開されると、候補者は自分の壁のポスター、そして大きなポスターの幅の差になります。また、候補者は、他のポスターは既に占有壁セグメント上に置かれ、そのポスターを開始します。みんなBytetown非常に好奇心が強い、選挙前の最後の日に自分のポスター(全部または一部)見えます。

あなたの仕事は、すべての可視のポスターポスターの数を見つけることです、そしてポスターの大きさに関係与え、

アイデア解析

タイトルを取得するには、このセクションのカバー、の最初に考えご覧ツリーラインを各投稿看板のために来、基本的な考え方があり、 リットル - R L_iを-R_iと 各クエリ間隔の看板のために私たち間隔内のすべての場所で、前回の1、 リットル R L_iを、R_iと それが1の場合の最小値は、それがカバーされていない少なくとも1であることを意味しています。しかし、妻の妻の大きな範囲。葉千万の木、私も勇気を持っていない建てることができませんでした。ディスクリート:、特定の薬の大規模な範囲をどのように行うのか。
ここに画像を挿入説明
これは、離散上の問題を追跡するためにԾ ㅂ Ծ難しいです,,私たちの簡単な離散化はこれです:個別プロファイル
ユニット1は、長さの単位、以下のとおりであるので、次の例(サンプルトピック)のようにの

  1   2   3   4  6   7   8   10

     —  —  —  —  —  —  —  —

  1   2   3   4  5   6   7   8

離散X [1] = 1; X [2] = 2; X [3] = 3; X [4] = 4; X [5] = 6; X [7] = 8; X [8] = 10

こうして順次次に大きいにマッピング小さい区間に区分し、8(セグメントツリーを有する)壁1の各柱幅、異なる色のセグメントの数の最終カウントアップデート。

しかし、ちょうどそう簡単な離散化は間違っています、

3枚のポスター:1〜10 1〜46〜10

離散X [1] = 1、X [2] = 4、X [3] = 6、X [4] = 10
第一張計時:1-4壁が1で染色され、
第二のポスター時間:1〜2壁は、依然として1~4染色2,3され、
第三の張計時:3-4壁は依然として3,1 2~2染色します。
最後に、最初のポスターは、出力2が、実際にはそれほど重要ではないのでことを、完全に覆われて表示され、それが正しい出力3です。

新しい離散法:中間体上の例14610のための部屋の数に追加1以上によって異なるが、(1,4および6,10の間の実際のアルゴリズムは数の間に追加される)5を加え

X [1] = 1、X [2] = 4、X [3] = 5、X [4] = 6、X [5] = 10

この後、5第1染色1であり、1〜2秒2を染色し、そして第4-5 3を染色しました

最後に、1〜2〜5 1、4、2、3、3、3て、出力正しい結果

ダウンツリーラインの問題であり、どのように離散、をよく知っツリーラインのチュートリアル+テンプレートこの質問は明らかにどこ我々は、ビルド操作する必要がありますが、間隔及び範囲のクエリを変更する必要はありませんされています。対数配列 S m [ ] 和[] 、我々は、操作入力部に応じて順次入力続行 l i [ i ] , r i [ i ] 李[i]は、ND [i]は、 、タグに取り付けられたセクション i は、すべての更新機能になり、

void pushdown(int rt)
{
    sum[rt<<1]=sum[rt];
    sum[rt<<1|1]=sum[rt];
    sum[rt]=-1;
}
void update(int L,int R,int C,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        sum[rt]=C;
        return ;
    }
    if(sum[rt]!=-1)
        pushdown(rt);
    int m=(l+r)>>1;
    if(m>=R) update(L,R,C,l,m,rt<<1);
    else if(L>m) update(L,R,C,m+1,r,rt<<1|1);
    else update(L,m,C,l,m,rt<<1),update(m+1,R,C,m+1,r,rt<<1|1);
}

あなたは全体の範囲が含まれている場合、この範囲を与える(そこの前にいるかどうか)このポスターのマークをカバーし、パーティション間、必要であれば、まず現在のノードの既存のマークプッシュダウンを行い、下位ノードを通過し、その後、下位ノードを更新し続けています。

同じクエリも改訂されます

void query(int l,int r,int rt)
{
        if(!vis[sum[rt]]&&sum[rt]!=-1)
        {
            ans++;
            vis[sum[rt]]=1;
        return ;
        }
    if(l==r)
    {
        return ;
    }
    if(sum[rt]!=-1)
        pushdown(rt);
    int m=(l+r)>>1;
    query(l,m,rt<<1);
    query(m+1,r,rt<<1|1);
}

ノードが現在のノードが最後のポスターカバーでそのマークを示すマークで覆われている場合にはポスターが統計されていない場合、その後、我々は++ ANS、またはバイナリクエリ。

チップ

  • 注プッシュダウン、そうでない場合、ツリー全体がゼロにプッシュされます、プッシュダウンに親を標識する必要があります。
  • 間隔の長さは、要素の数が繰り返されないことに注意してください、クエリ/更新範囲との間のツリー関係。
  • 最初のルートは0にならないでください
#include<math.h>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=10005;
int n;
int vis[maxn<<3],sum[maxn<<4];
int li[maxn*2],ri[maxn*2],lsh[maxn<<2];
void pushdown(int rt)
{
    sum[rt<<1]=sum[rt];
    sum[rt<<1|1]=sum[rt];
    sum[rt]=-1;
}
void update(int L,int R,int C,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        sum[rt]=C;
        return ;
    }
    if(sum[rt]!=-1)
        pushdown(rt);
    int m=(l+r)>>1;
    if(m>=R) update(L,R,C,l,m,rt<<1);
    else if(L>m) update(L,R,C,m+1,r,rt<<1|1);
    else update(L,m,C,l,m,rt<<1),update(m+1,R,C,m+1,r,rt<<1|1);
}
int ans;
void query(int l,int r,int rt)
{
        if(!vis[sum[rt]]&&sum[rt]!=-1)
        {
            ans++;
            vis[sum[rt]]=1;
        return ;
        }
    if(l==r)
    {
        return ;
    }
    if(sum[rt]!=-1)
        pushdown(rt);
    int m=(l+r)>>1;
    query(l,m,rt<<1);
    query(m+1,r,rt<<1|1);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        memset(sum,-1,sizeof(sum));
        memset(vis,0,sizeof(vis));
        int tot=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&li[i],&ri[i]);
            lsh[tot++]=li[i];
            lsh[tot++]=ri[i];
        }
        sort(lsh,lsh+tot);
        int mm=unique(lsh,lsh+tot)-lsh;
        int tt=mm;
        for(int i=1;i<tt;i++)
        {
            if(lsh[i]-lsh[i-1]>1)
                lsh[mm++]=lsh[i-1]+1;
        }
        sort(lsh,lsh+mm);
        for(int i=0;i<n;i++)
        {
            int x=lower_bound(lsh,lsh+mm,li[i])-lsh;
            int y=lower_bound(lsh,lsh+mm,ri[i])-lsh;
            update(x,y,i,0,mm-1,1);
        }
        ans=0;
        query(0,mm-1,1);
        printf("%d\n",ans);
    }
}
公開された186元の記事 ウォン称賛13 ビュー9309

おすすめ

転載: blog.csdn.net/csyifanZhang/article/details/105186519