+セグメントツリーの更新間隔の離散 - 市長ポスターPOJ - 2528

市長のポスターPOJ - 2528

問題の意味:
N-(N - <= 10000)が順次個別ポスター、それぞれ所定の範囲のLi、RI(1 <=リーに固定ポスター <= RI <= 10000000)。最後のポスターはどのように多くの検索を見ることができます。

アイデア:
ツリーライン間隔更新の問題は、あなたが、セグメントツリー用に最適化された怠惰な思考を更新することができますあまりにも明らか千万で、配列はできませんが、唯一のn 10000、離散程度することができます。
しかし、このタイトルの離散的な問題(ピット)があり、それは我々がしっかり圧縮の隣にあるためであるので、カバレッジ・エラーの問題が存在してもよい
。例えば、データ
3
1 10
1 3
7 10
圧縮後我々がなるべきです
4 1
1 2
3 4
私たちは、あなたがカバーされる最初の2つだけのセクションを視覚的な外観を見ることができます。本当の答えは3匹の魚である必要があり
、これは、我々は、C内の離散配列に格納する必要があるものです右境界R + 1のそれぞれを考えるとき、それが効果的にエラー・カバレッジの問題を回避することができるようにも保存されています。

問題のコード:

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5;
int st[maxn * 4], vis[maxn * 2], cnt[maxn * 2], a[maxn * 2];
int ans;

void pushdown(int o){     //懒人更新 

	if(st[o]) st[o << 1] = st[o << 1 | 1] = st[o], st[o] = 0;

}

void updata(int o, int l, int r, int L, int R,int res){
	if(l >= L && r <= R){
		st[o] = res;
		return;
	}
	int m = (l + r) >> 1;
	pushdown(o);
	if(L <= m) updata(o << 1, l, m, L, R, res);
	if(R > m) updata(o << 1 | 1, m + 1, r, L, R, res);
}

void query(int o, int l, int r){
	if(st[o]) {
	    if(!vis[st[o]] && st[o] != 0){
		   vis[st[o]] = 1;
		   ans++;
		} 
		return;
	}
	if(l == r) return ;
	int m = (l + r) >> 1;
	pushdown(o);
	query(o << 1, l, m);
	query(o << 1 | 1, m + 1, r);
}
int main(){
	int c, n;
	scanf("%d", &c);
	while(c--){
	    scanf("%d", &n);
	    int cot = 0; 
		for(int i = 0; i < n; i++){
			scanf("%d%d", &cnt[i * 2], &cnt[i * 2 + 1]);
			a[cot++] = cnt[i * 2];
			a[cot++] = cnt[i * 2 + 1];
			a[cot++] = cnt[i * 2 + 1] + 1;
		} 
		sort(a, a + cot); 
		int tot = (int)(unique(a, a + cot) - a);  //unique函数返回值为第一个重复元素的指针
		for(int i = 0; i < 2 * n; i++)
		cnt[i] = (int)(lower_bound(a, a + cot, cnt[i]) - a + 1);
		
		ans = 0;                               //初始化 
		fill(vis, vis + 2 * tot + 1, 0);
		fill(st, st + 4 * tot + 1, 0);
		
		for(int i = 0; i < n; i++){
			updata(1, 1, tot, cnt[i * 2], cnt[i * 2 + 1], i + 1);
		
		}
		
		query(1, 1, tot);
		
		printf("%d\n", ans);
			
	}
}

正しいコード:

#include<iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lc p<<1,s,mid
#define rc p<<1|1,mid+1,e
#define mid ((s+e)>>1)
#define CLR(A) memset(A,0,sizeof(A))
using namespace std;
 
const int N = 20005;
int col[N * 4], vis[N];
int le[N], ri[N], c[N * 2], ans;
 
void pushdown(int p)
{
    if(col[p] == -1) return;
    col[p << 1] = col[p << 1 | 1]  = col[p];
    col[p] = -1;
}
 
void update(int p, int s, int e, int l, int r, int v)
{
    if(s >= l && e <= r)
    {
        col[p] = v;
        return;
    }
    pushdown(p);
    if(l <= mid) update(lc, l, r, v);
    if(r > mid) update(rc, l, r, v);
}
 
void query(int p, int s, int e)
{
    if(col[p] != -1)
    {
        if(!vis[col[p]])
            vis[col[p]] = 1, ++ans;
        return;
    }
    query(lc);
    query(rc);
}
 
int compress(int n) //离散化
{
    int k = 0;
    for(int i = 0; i < n; ++i)
    {
        c[k++] = le[i];
        c[k++] = ri[i];
        c[k++] = ri[i] + 1;
    }
    sort(c, c + k);
    return unique(c, c + k) - c - 1;
}
 
int main()
{
    int cas, m, n, l, r;
    scanf("%d", &cas);
    while(cas--)
    {
        scanf("%d", &m);
        for(int i = 0; i < m; ++i)
            scanf("%d%d", &le[i], &ri[i]);
        n = compress(m);
    
        cout << "n = " << n << endl;
        
        
         ans = 0;
        CLR(col), CLR(vis);
        for(int i = 0; i < m; ++i)
        {
            l = lower_bound(c, c + n, le[i]) - c + 1;
            r = lower_bound(c, c + n, ri[i]) - c + 1;
            update(1, 1, n, l, r, i + 1);
        }
        vis[0] = 1;
        query(1, 1, n);
        printf("%d\n", ans);
    }
    return 0;
}
公開された92元の記事 ウォン称賛7 ビュー3727

おすすめ

転載: blog.csdn.net/dajiangyou123456/article/details/104443727