POJ 2528 - Mayor's posters
2012-07-23 09:43
357 查看
题目地址 : http://poj.org/problem?id=2528
PS: 其实代码还是还是很水的。有个地方可以优化但不知怎么优化。
这题RE了很多次,貌似是题目数据超范围了?但是我用 if(n>maxn)while(1);来检测,并没有TLE~~
而我范围确实是开了4*maxn。。。后来直接开 8*maxn(很奇怪的是,发现下面的错误之后,改正之后不RE了~~ 囧~
)
但是这样还是WA了~~ 看了discuss,终于发现了一组错误数据~~~ 查看之后,发现是离散化出问题~~
因为是线段覆盖,按先后顺序覆盖3个线段 1~10、1~4
、7~10,其中5~6的空间是第一条线段的。而离散化之后,变成了 1~4、1~2、3~4,因此第一条线段完全被遮住了~~~~~ 囧哭了~~
之前以为用的方法搓了,所以还写了另一个。现在有两种方法。
方法一:每个线段都有一个val。线段覆盖,每次更新,将之前的覆盖过的线段重复部分覆盖掉,即区间赋值为val。最后计算的时候,查询有多少个不同的val。
方法二:每个线段都保存一个长度,每次更新,将区间标记成该次更新的线段的标号。下次更新时,如果有重复部分,就找到重复部分的已存在的线段标号,将该标号所代表的线段长度减去此重复区间的长度。那么,如果最后还有长度剩余,就表示没有被完全覆盖。
于是最后统计的时候,只需要找到有多少个len大于0的线段即可。
PS: 其实代码还是还是很水的。有个地方可以优化但不知怎么优化。
这题RE了很多次,貌似是题目数据超范围了?但是我用 if(n>maxn)while(1);来检测,并没有TLE~~
而我范围确实是开了4*maxn。。。后来直接开 8*maxn(很奇怪的是,发现下面的错误之后,改正之后不RE了~~ 囧~
)
但是这样还是WA了~~ 看了discuss,终于发现了一组错误数据~~~ 查看之后,发现是离散化出问题~~
因为是线段覆盖,按先后顺序覆盖3个线段 1~10、1~4
、7~10,其中5~6的空间是第一条线段的。而离散化之后,变成了 1~4、1~2、3~4,因此第一条线段完全被遮住了~~~~~ 囧哭了~~
之前以为用的方法搓了,所以还写了另一个。现在有两种方法。
方法一:每个线段都有一个val。线段覆盖,每次更新,将之前的覆盖过的线段重复部分覆盖掉,即区间赋值为val。最后计算的时候,查询有多少个不同的val。
方法二:每个线段都保存一个长度,每次更新,将区间标记成该次更新的线段的标号。下次更新时,如果有重复部分,就找到重复部分的已存在的线段标号,将该标号所代表的线段长度减去此重复区间的长度。那么,如果最后还有长度剩余,就表示没有被完全覆盖。
于是最后统计的时候,只需要找到有多少个len大于0的线段即可。
//方法一: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll (v<<1) #define rr (v<<1|1) #define tmid ((l+r)>>1) using namespace std; const int maxn=11000; int flag[maxn*16]; bool vis[maxn]; int n,nn,cnt,sum; int s[maxn*2],res[maxn*2],dir[maxn*2]; int cmp(int a,int b){ return s[a]<s[b]; } void deal(){ int i; nn=n<<1; for(i=0;i<nn;i++) dir[i]=i; sort(dir,dir+nn,cmp); // for(i=0;i<nn;i++) cout<<dir[i]<<" ";cout<<endl; res[dir[0]]=cnt=1; for(i=1;i<nn;i++) if(s[dir[i]]==s[dir[i-1]]) res[dir[i]]=cnt; else if(s[dir[i]]>s[dir[i-1]]+1) res[dir[i]]=(cnt+=2); else res[dir[i]]=(cnt+=1); // for(i=0;i<n;i++) cout<<res[i]<<" "<<res[i+n]<<endl; memset(vis,false,sizeof(vis)); } void make_tree(int l,int r,int v){ flag[v]=-1; if(l==r) return; make_tree(l,tmid,ll); make_tree(tmid+1,r,rr); } void update(int val,int li,int ri,int l,int r,int v){ if(li>r || ri<l) return; if(li<=l && r<=ri){ flag[v]=val; return; } if(l==r) while(1); if(flag[v]!=-2){ flag[ll]=flag[rr]=flag[v]; flag[v]=-2; } update(val,li,ri,tmid+1,r,rr); update(val,li,ri,l,tmid,ll); } int query(int l,int r,int v){ if(flag[v]==-1) return 0; if(flag[v]>=0){ if(vis[flag[v]]) return 0; vis[flag[v]]=true; return 1; } return query(l,tmid,ll)+query(tmid+1,r,rr); } int main(){ int t,i; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i=0;i<n;i++) scanf("%d%d",&s[i],&s[n+i]); deal(); make_tree(1,cnt,1); for(i=0;i<n;i++) update(i,res[i],res[i+n],1,cnt,1); printf("%d\n",query(1,cnt,1)); } return 0; } /* 3 3 5 6 4 5 6 8 3 1 10 1 3 6 10 5 1 4 2 6 8 10 3 4 7 10 */
//方法二: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll (v<<1) #define rr (v<<1|1) #define tmid ((l+r)>>1) using namespace std; const int maxn=11000; int flag[maxn*16]; int len[maxn]; int n,nn,cnt,sum; int s[maxn*2],res[maxn*2],dir[maxn*2]; int cmp(int a,int b){ return s[a]<s[b]; } void deal(){ int i; nn=n<<1; for(i=0;i<nn;i++) dir[i]=i; sort(dir,dir+nn,cmp); // for(i=0;i<nn;i++) cout<<dir[i]<<" ";cout<<endl; res[dir[0]]=cnt=1; for(i=1;i<nn;i++) if(s[dir[i]]==s[dir[i-1]]) res[dir[i]]=cnt; else if(s[dir[i]]>s[dir[i-1]]+1) res[dir[i]]=(cnt+=2); else res[dir[i]]=(cnt+=1); // for(i=0;i<n;i++) cout<<res[i]<<" "<<res[i+n]<<endl; memset(len,0,sizeof(len)); } void make_tree(int l,int r,int v){ flag[v]=-1; if(l==r) return; make_tree(l,tmid,ll); make_tree(tmid+1,r,rr); } void update(int val,int li,int ri,int l,int r,int v){ if(ri<l || li>r) return; if(li<=l && r<=ri){ if(flag[v]>=0) len[flag[v]]-=r-l+1; else if(flag[v]==-2){ update(val,li,ri,l,tmid,ll); update(val,li,ri,tmid+1,r,rr); } flag[v]=val; return ; } if(flag[v]!=-2){ flag[ll]=flag[rr]=flag[v]; flag[v]=-2; } update(val,li,ri,l,tmid,ll); update(val,li,ri,tmid+1,r,rr); } int main(){ int t,i; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i=0;i<n;i++) scanf("%d%d",&s[i],&s[n+i]); deal(); make_tree(1,cnt,1); for(i=0;i<n;i++) update(i,res[i],res[i+n],1,cnt,1),len[i]=res[i+n]-res[i]+1; for(sum=0,i=0;i<n;i++) if(len[i]>0) sum++; printf("%d\n",sum); } return 0; }
相关文章推荐
- 线段树区间更新,区间统计+离散化 POJ 2528 Mayor's posters
- POJ 2528 Mayor's posters(离散化线段树)
- POJ 2528 Mayor's posters
- POJ - 2528 Mayor's posters(线段树)
- POJ_2528_Mayor's posters
- Poj 2528 Mayor's posters
- poj 2528 Mayor's posters
- POJ 2528 Mayor's posters(线段树离散化)
- poj 2528 Mayor's posters(线段树,离散化,成段更新染色)
- POJ 2528 Mayor's posters 题解
- POJ 2528 Mayor's posters(离散化 + 线段树)
- POJ 2528 Mayor's posters
- POJ 2528 Mayor's posters(成段更新)
- poj 2528 Mayor's posters(数据结构:线段树+离散化)
- POJ 2528 Mayor's posters(离散化 线段树 贴海报)
- POJ 2528-Mayor's posters(线段树区间染色+离散化)
- POJ 2528 Mayor's posters(区间更新 + 离散化)
- POJ 2528 Mayor's posters(线段树染色+离散化)
- poj 2528 Mayor's posters
- poj 2528 Mayor's posters(线段树+离散化)