POJ 2528 - Mayor's posters

来源:互联网 发布:java获取文件的后缀名 编辑:程序博客网 时间:2024/05/20 18:46

题目地址 : http://poj.org/problem?id=2528

 

 

PS 其实代码还是还是很水的。有个地方可以优化但不知怎么优化。

 

       这题RE了很多次,貌似是题目数据超范围了?但是我用 if(n>maxn)while(1);来检测,并没有TLE~~ 而我范围确实是开了4*maxn。。。后来直接开 8*maxn(很奇怪的是,发现下面的错误之后,改正之后不RE~~ ~

 

       但是这样还是WA~~ 看了discuss,终于发现了一组错误数据~~~  查看之后,发现是离散化出问题~~ 

因为是线段覆盖,按先后顺序覆盖3个线段 1~101~47~10,其中5~6的空间是第一条线段的。而离散化之后,变成了 1~41~23~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;}/*335 64 56 831 101 36 1051 42 68 103 47 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;}


 

原创粉丝点击