poj2528 &&poj2777
2016-01-22 14:16
330 查看
poj2528 线段树+离散化 (2777在下面)
10000000的宽度太大 必须对数据进行离散化处理
比如 (1,10000)(5000,20000)这两张海报 可以离散为(1,3)(2,4)
具体处理办法看代码
注意 (1,4)(2 , 9)(8 ,10) 离散化为(1 , 3)(2,5)(4,6)即{由(1,2,4,8,9,10)到(1,2,3,4,5,6)}是错误的 明显原数据(1,4)和(8, 10)
并不能完全遮盖(2,9),结果应该是3 ;但是离散后的数据结果却是2;
可以这样(1,2,4,8,9,10)在2,4直接加入3; 在4,8之间加入5;变为(1,2,3,4,5,8,9,10)然后离散化处理为(1,2,3,4,5,6,7,8);
离散化借助stl容器会超时 set map都不能用!
poj2777
和上一个题差不多 但注意的点更多
1,区间(a,b)a可能大于b
2,查询时时不要忘了判断区间
3,查询时不要忘了pushdown
4,查询时的pushdown和updata时的pushdown不太一样 否则会超时
上代码
10000000的宽度太大 必须对数据进行离散化处理
比如 (1,10000)(5000,20000)这两张海报 可以离散为(1,3)(2,4)
具体处理办法看代码
注意 (1,4)(2 , 9)(8 ,10) 离散化为(1 , 3)(2,5)(4,6)即{由(1,2,4,8,9,10)到(1,2,3,4,5,6)}是错误的 明显原数据(1,4)和(8, 10)
并不能完全遮盖(2,9),结果应该是3 ;但是离散后的数据结果却是2;
可以这样(1,2,4,8,9,10)在2,4直接加入3; 在4,8之间加入5;变为(1,2,3,4,5,8,9,10)然后离散化处理为(1,2,3,4,5,6,7,8);
离散化借助stl容器会超时 set map都不能用!
#include<iostream> #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<set> #include<map> #define maxn 1000100 using namespace std; int _set[maxn*2]; bool vis[11000]; int fin_ans; void pushdown(int o,int l,int r) { if(_set[o]!=-1) { _set[o*2]=_set[o]; _set[o*2+1]=_set[o]; _set[o]=-1; } } void updata(int o,int l,int r,int target_l,int target_r,int setv) { if(target_l<=l && r<=target_r) { _set[o]=setv; return ; } int m=(l+r)/2; pushdown(o,l,r); if(target_l<=m) updata(o*2,l,m,target_l,target_r,setv); if(m<target_r) updata(o*2+1,m+1,r,target_l,target_r,setv); } //void query(int o,int l,int r)//不必查询到叶子节点 //{ // if(l==r) // { // if(!vis[_set[o]]) // { // fin_ans++; // vis[_set[o]]=true; // } // return ; // } // pushdown(o,l,r); // int m=(l+r)/2; // query(o*2,l,m); // query(o*2+1,m+1,r); //} void query(int o,int l,int r) { if (_set[o] != -1) { if (!vis[_set[o]]) fin_ans ++; vis[_set[o] ] = true; return ; } if (l == r) return ; int m = (l + r) >> 1; query(o*2,l,m); query(o*2+1,m+1,r); } int arr_l[11000]; int arr_r[11000]; int temp[41000]; int main() { int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); int i,pos=0; for(i=0;i<n;++i) { scanf("%d%d",&arr_l[i],&arr_r[i]); temp[pos++]=arr_l[i]; temp[pos++]=arr_r[i]; } int t=1; sort(temp,temp+pos); for(i=1;i<pos;++i) { if(temp[i]!=temp[i-1]) temp[t++]=temp[i]; } int tt=t; for(i=1;i<t;++i) { if(temp[i]-temp[i-1]!=1) temp[tt++]=temp[i-1]+1; } sort(temp,temp+tt); // int tt=1; // map<int,int>_hash; // int bac; // for(i=0;i<t;i++) // { // if(i==0) // { // bac=temp[i]; // _hash[bac]=tt++; // } // else // { // if(temp[i]-bac>1) // { // tt++; // } // bac=temp[i]; // _hash[bac]=tt++; // } // } memset(_set,-1,sizeof(_set)); memset(vis,false,sizeof(vis)); for(i=0;i<n;++i) { // int l=_hash[arr_l[i]]; // int r=_hash[arr_r[i]]; int l=lower_bound(temp,temp+tt,arr_l[i])-temp; int r=lower_bound(temp,temp+tt,arr_r[i])-temp; updata(1,0,tt-1,l,r,i); } fin_ans=0; query(1,0,tt-1); printf("%d\n",fin_ans); } }
poj2777
和上一个题差不多 但注意的点更多
1,区间(a,b)a可能大于b
2,查询时时不要忘了判断区间
3,查询时不要忘了pushdown
4,查询时的pushdown和updata时的pushdown不太一样 否则会超时
上代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<climits> #include<queue> #define mem(a) memset(a,0,sizeof(a)) #define maxn 110000 using namespace std; int _set[maxn<<2]; bool vis[50];//因为用memset清0 ,太大就可能会超时 int temp; void pushdown(int o)//更新时使用 更改当前的——set[o] { if(_set[o]!=-1) { _set[o*2]=_set[o]; _set[o*2+1]=_set[o]; _set[o]=-1; } } void pushdownq(int o)//查询时使用 不更改当前节点的_set[o],查询时如果使用pushdown()会超时 { if(_set[o]!=-1) { _set[o*2]=_set[o]; _set[o*2+1]=_set[o]; } } void updata(int o,int l,int r,int ql,int qr,int setv) { if(ql<=l && r<=qr) { _set[o]=setv; return ; } int m=(l+r)/2; pushdown(o); if(ql<=m) { updata(o*2,l,m,ql,qr,setv); } if(m<qr) { updata(o*2+1,m+1,r,ql,qr,setv); } } void inque(int o,int l,int r,int ql,int qr)//ql,qr制定了查找范围 所以需要pushdown { if(_set[o]!=-1 && ql<=l && r<=qr) { if(!vis[_set[o]]) { temp++; vis[_set[o]]=true; } return; } pushdownq(o);//使用pushdown超时 if(l==r) return; int m=(l+r)/2; if(ql<=m) inque(o*2,l,m,ql,qr); if(m<qr) inque(o*2+1,m+1,r,ql,qr); } int query(int a,int b,int L) { temp=0; memset(vis,false,sizeof(vis)); inque(1,1,L,a,b); return temp; } int main() { int L,T,O; memset(_set,-1,sizeof(_set)); scanf("%d%d%d",&L,&T,&O); _set[1]=1;//颜色全部为1 while(O--) { char key[5]; int a,b,c; scanf("%s",key); switch(key[0]) { case 'C': scanf("%d%d%d",&a,&b,&c); if(a>b) swap(a,b); updata(1,1,L,a,b,c); break; case 'P': scanf("%d%d",&a,&b); if(a>b) swap(a,b); printf("%d\n",query(a,b,L)); break; } // cout<<_set[1]<<"SET!\n"; } }
相关文章推荐
- ubntu 下mysql 允许远程访问
- Swift 2.0初探:值得注意的新特性
- flashback transaction闪回事务查询
- C# 连接 mySQL 出现 GUID 应包含带 4 个短划线的 32 位数 问题
- android 自定义文本组合控件
- MFC 技巧之一
- oracle 闪回功能详解
- ASP.Net中Session失效的一种编程思路
- 项目报错,tomcat中引起
- Mysql5.7.10新加用户
- ERROR:in where clause is ambiguous
- Android 讲解:AsyncTask
- Apache+Tomcat集群配置
- 图片轮播效果
- Yii2国际化i18n配置的基本步骤
- 不错的UIPageControl替代控件TAPageControl
- 通用商城系统V5.0
- 一些常用的查找方法,记录备用
- C语言中volatile关键字的作用
- Spring获取单例getSingleton(1)