• POJ 2528 Mayor's posters 离散化+线段树


    题目大意:给出一些海报和贴在墙上的区间。问这些海报依照顺序贴完之后,最后能后看到多少种海报。


    思路:区间的范围太大,然而最多仅仅会有10000张海报,所以要离散化。

    之后用线段树随便搞搞就能过。

    关键是离散化的方法,这个题我时隔半年才A掉,之前一直就TTT,我还以为是线段树写挂了。

    当我觉得我自己的水平这样的水线段树已经基本写不挂的时候又写了这个题,竟然还是T。

    后来我对照别人的代码,才发现是我的离散化写渣了。

    以下附AC代码(79ms),这个离散化写的比較优雅。时间也非常快,以后就这么写了。


    CODE(POJ 79ms):


    #include <map>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 100010
    #define LEFT (pos << 1)
    #define RIGHT (pos << 1|1)
    using namespace std;
    
    pair<int,int> interval[MAX];
    pair<int,int *> src[MAX << 1];
    
    int cases;
    int tree[MAX << 2];
    int intervals;
    int cnt,t;
    bool color[MAX];
    
    inline void Initialize()
    {
    	t = cnt = 0;
    	memset(color,false,sizeof(color));
    	memset(tree,0,sizeof(tree));
    }
    
    inline void PushDown(int pos)
    {
    	if(tree[pos]) {
    		tree[LEFT] = tree[pos];
    		tree[RIGHT] = tree[pos];
    		tree[pos] = 0;
    	}
    }
    
    inline void Modify(int l,int r,int x,int y,int pos,int c)
    {
    	if(l == x && y == r) {
    		tree[pos] = c;
    		return ;
    	}
    	PushDown(pos);
    	int mid = (l + r) >> 1;
    	if(y <= mid)	Modify(l,mid,x,y,LEFT,c);
    	else if(x > mid)	Modify(mid + 1,r,x,y,RIGHT,c);
    	else {
    		Modify(l,mid,x,mid,LEFT,c);
    		Modify(mid + 1,r,mid + 1,y,RIGHT,c);
    	}
    }
    
    void GetAns(int l,int r,int pos)
    {
    	if(tree[pos]) {
    		color[tree[pos]] = true;
    		return ;
    	}
    	if(l == r)	return ;
    	int mid = (l + r) >> 1;
    	GetAns(l,mid,LEFT);
    	GetAns(mid + 1,r,RIGHT);
    }
    
    int main()
    {
    	for(cin >> cases; cases; --cases) {
    		scanf("%d",&intervals);
    		Initialize();
    		for(int i = 1; i <= intervals; ++i) {
    			scanf("%d%d",&interval[i].first,&interval[i].second);
    			src[++cnt] = make_pair(interval[i].first,&interval[i].first);
    			src[++cnt] = make_pair(interval[i].second,&interval[i].second);
    		}
    		sort(src + 1,src + cnt + 1);
    		for(int i = 1; i <= cnt; ++i)
    		{
    			if(src[i].first != src[i - 1].first)	++t;
    			*src[i].second = t;
    		}
    		for(int i = 1; i <= intervals; ++i)
    			Modify(1,cnt,interval[i].first,interval[i].second,1,i);
    		GetAns(1,cnt,1);
    		int ans = 0;
    		for(int i = 1; i <= intervals; ++i)
    			ans += color[i];
    		printf("%d
    ",ans);
    	}
    	return 0;
    }

    为了警醒后人,也为了警醒自己(以后再也不这么写离散化了)。我将我T的离散化代码也发上来,好孩子千万不要学习。


    CODE(POJ TLE):


    #include <map>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 1000010
    #define LEFT (pos << 1)
    #define RIGHT (pos << 1|1)
    using namespace std;
    
    pair<int,int> interval[MAX];
    map<int,int> G;
    
    int cases;
    int tree[MAX << 2];
    int intervals,src[MAX << 1];
    int cnt,t;
    bool color[MAX];
    
    inline void Initialize()
    {
    	G.clear();
    	t = cnt = 0;
    	memset(color,false,sizeof(color));
    	memset(tree,0,sizeof(tree));
    }
    
    inline void PushDown(int pos)
    {
    	if(tree[pos]) {
    		tree[LEFT] = tree[pos];
    		tree[RIGHT] = tree[pos];
    		tree[pos] = 0;
    	}
    }
    
    inline void Modify(int l,int r,int x,int y,int pos,int c)
    {
    	if(l == x && y == r) {
    		tree[pos] = c;
    		return ;
    	}
    	PushDown(pos);
    	int mid = (l + r) >> 1;
    	if(y <= mid)	Modify(l,mid,x,y,LEFT,c);
    	else if(x > mid)	Modify(mid + 1,r,x,y,RIGHT,c);
    	else {
    		Modify(l,mid,x,mid,LEFT,c);
    		Modify(mid + 1,r,mid + 1,y,RIGHT,c);
    	}
    }
    
    void GetAns(int l,int r,int pos)
    {
    	if(tree[pos]) {
    		color[tree[pos]] = true;
    		return ;
    	}
    	if(l == r)	return ;
    	int mid = (l + r) >> 1;
    	GetAns(l,mid,LEFT);
    	GetAns(mid + 1,r,RIGHT);
    }
    
    int main()
    {
    	for(cin >> cases; cases; --cases) {
    		scanf("%d",&intervals);
    		Initialize();
    		for(int i = 1; i <= intervals; ++i) {
    			scanf("%d%d",&interval[i].first,&interval[i].second);
    			src[++cnt] = interval[i].first;
    			src[++cnt] = interval[i].second;
    		}
    		sort(src + 1,src + cnt + 1);
    		G[src[1]] = ++t;
    		for(int i = 2; i <= cnt; ++i)
    			if(src[i] != src[i - 1])
    				G[src[i]] = ++t;
    		for(int i = 1; i <= intervals; ++i)
    			Modify(1,cnt,G[interval[i].first],G[interval[i].second],1,i);
    		GetAns(1,cnt,1);
    		int ans = 0;
    		for(int i = 1; i <= intervals; ++i)
    			ans += color[i];
    		printf("%d
    ",ans);
    	}
    	return 0;
    }


    后来我和小伙伴门一起研究了这样的离散化方法,正常来说是不会T的,尽管多带了一个log。可是这个题是多组数据啊。坑啊,每一组数据就要clear一下map。据老师说map的clear是一个一个删的。。

    。于是机制的我就每次new一个map,这样就不用clear了。结果交上去果然A了。


    CODE(POJ 344ms):


    #include <map>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 1000010
    #define LEFT (pos << 1)
    #define RIGHT (pos << 1|1)
    using namespace std;
    
    pair<int,int> interval[MAX];
    map<int,int> *G;
    
    int cases;
    int tree[MAX << 2];
    int intervals,src[MAX << 1];
    int cnt,t;
    bool color[MAX];
    
    inline void Initialize()
    {
    	G = new map<int,int>;
    	t = cnt = 0;
    	memset(color,false,sizeof(color));
    	memset(tree,0,sizeof(tree));
    }
    
    inline void PushDown(int pos)
    {
    	if(tree[pos]) {
    		tree[LEFT] = tree[pos];
    		tree[RIGHT] = tree[pos];
    		tree[pos] = 0;
    	}
    }
    
    inline void Modify(int l,int r,int x,int y,int pos,int c)
    {
    	if(l == x && y == r) {
    		tree[pos] = c;
    		return ;
    	}
    	PushDown(pos);
    	int mid = (l + r) >> 1;
    	if(y <= mid)	Modify(l,mid,x,y,LEFT,c);
    	else if(x > mid)	Modify(mid + 1,r,x,y,RIGHT,c);
    	else {
    		Modify(l,mid,x,mid,LEFT,c);
    		Modify(mid + 1,r,mid + 1,y,RIGHT,c);
    	}
    }
    
    void GetAns(int l,int r,int pos)
    {
    	if(tree[pos]) {
    		color[tree[pos]] = true;
    		return ;
    	}
    	if(l == r)	return ;
    	int mid = (l + r) >> 1;
    	GetAns(l,mid,LEFT);
    	GetAns(mid + 1,r,RIGHT);
    }
    
    int main()
    {
    	for(cin >> cases; cases; --cases) {
    		scanf("%d",&intervals);
    		Initialize();
    		for(int i = 1; i <= intervals; ++i) {
    			scanf("%d%d",&interval[i].first,&interval[i].second);
    			src[++cnt] = interval[i].first;
    			src[++cnt] = interval[i].second;
    		}
    		sort(src + 1,src + cnt + 1);
    		(*G)[src[1]] = ++t;
    		for(int i = 2; i <= cnt; ++i)
    			if(src[i] != src[i - 1])
    				(*G)[src[i]] = ++t;
    		for(int i = 1; i <= intervals; ++i)
    			Modify(1,cnt,(*G)[interval[i].first],(*G)[interval[i].second],1,i);
    		GetAns(1,cnt,1);
    		int ans = 0;
    		for(int i = 1; i <= intervals; ++i)
    			ans += color[i];
    		printf("%d
    ",ans);
    	}
    	return 0;
    }


  • 相关阅读:
    时间管理(二):时间管理的六项基本原则
    时间管理(一): 达成目标需重视时间管理
    oracle 工作机制 如何工作的
    如何快速彻底删除 svn checkout出来的文件夹
    win7 安装oracle11g注意事项
    eclipse findbugs does not match outer scope rule: MutexSchedulingRule encounter a pro
    oracle ora12154 无法解析连接字符串
    oracle 动态执行表不可访问 异常处理
    log4j配置
    linux 永久 修改 主机名 ip
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6803547.html
Copyright © 2020-2023  润新知