効果の対象に
我慢できないアブダビ(Bytetown)市民は、市長候補の選挙運動は喜んで国の選挙ポスターを入れてきました。市議会は最終的に場所の選挙ポスターに壁を建設することを決定し、そして次のルールの導入:
各候補者は、壁にポスターを置くことができます。
すべてのポスター壁の高さは、高さに等しい、ポスターの幅は、バイトの任意の整数(町のバイトのバイト長)であってもよいです。
なお、壁部、1バイトの幅の各部分を複数に分割されています。
各ポスターは完全に、より連続壁セグメントをカバーしなければなりません。
彼らは(すべての候補者を収容するのに十分なスペースを持つために)長い壁バイト千万の壁を構築しました。キャンペーンが再開されると、候補者は自分の壁のポスター、そして大きなポスターの幅の差になります。また、候補者は、他のポスターは既に占有壁セグメント上に置かれ、そのポスターを開始します。みんなBytetown非常に好奇心が強い、選挙前の最後の日に自分のポスター(全部または一部)見えます。
あなたの仕事は、すべての可視のポスターポスターの数を見つけることです、そしてポスターの大きさに関係与え、
アイデア解析
タイトルを取得するには、このセクションのカバー、の最初に考えご覧ツリーラインを各投稿看板のために来、基本的な考え方があり、
各クエリ間隔の看板のために私たち間隔内のすべての場所で、前回の1、
それが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て、出力正しい結果
ダウンツリーラインの問題であり、どのように離散、をよく知っツリーラインのチュートリアル+テンプレート。この質問は明らかにどこ我々は、ビルド操作する必要がありますが、間隔及び範囲のクエリを変更する必要はありませんされています。対数配列 、我々は、操作入力部に応じて順次入力続行 、タグに取り付けられたセクション は、すべての更新機能になり、
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);
}
}