Color the Ball(懵逼题)
Color the Ball |
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) |
Total Submission(s): 48 Accepted Submission(s): 25 |
Problem Description
There are infinite balls in a line (numbered 1 2 3 ....), and initially all of them are paint black. Now Jim use a brush paint the balls, every time give two integers a b and follow by a char 'w' or 'b', 'w' denotes the ball from a to b are painted white, 'b' denotes that be painted black. You are ask to find the longest white ball sequence.
|
Input
First line is an integer N (<=2000), the times Jim paint, next N line contain a b c, c can be 'w' and 'b'.
There are multiple cases, process to the end of file. |
Output
Two integers the left end of the longest white ball sequence and the right end of longest white ball sequence (If more than one output the small number one). All the input are less than 2^31-1. If no such sequence exists, output "Oh, my god". |
Sample Input
3 1 4 w 8 11 w 3 5 b |
Sample Output
8 11 |
Author
ZHOU, Kai
|
Source
ZOJ Monthly, February 2005
|
Recommend
Ignatius.L
|
因为这个专题都是线段树嘛,刚开始离散化进行区间合并,但是写着写着就爆了,后来又想了一下,不用合并,只要
set一下记录区间就行,但是边界问题各种wa,没忍住看了一发题解,看到暴力可以搞,结果就暴力一发就过了.......
就过了......
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; #define INF 0x3f3f3f3f char a[100002];//数组开小了,wa了几次 int n,x,y; char ch; void init(){ memset(a,'b',sizeof(a)); } int main(){ // freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF){ init(); int maxnum=0,minnum=INF;//数据的范围 for(int i=0;i<n;i++){ cin>>x>>y>>ch;//cin处理方便的点 if(y>maxnum) maxnum=y; if(x<minnum) minnum=x; for(int j=x;j<=y;j++)//模拟染色 a[j]=ch; } int sum=0;//记录连续白球的个数 int max1=0;//记录最多连续白球个数 int beg=minnum,end=minnum;//记录连续白球的区间 int minpos=-1,maxpos=-1;//最大连续白球的左右区间 for(int i=minnum;i<=maxnum+1;i++){ if(a[i]=='b'){//如果当前位置是黑球的话 if(sum>max1){ max1=sum; minpos=beg; maxpos=end; } sum=0; continue; } if(sum==0) beg=i; sum++; end=i; } if(max1==0) cout<<"Oh, my god"<<endl; else cout<<minpos<<" "<<maxpos<<endl; } return 0; }
经过离散化处理的线段树
/* * @Author: lyucheng * @Date: 2017-07-03 21:05:51 * @Last Modified by: lyucheng * @Last Modified time: 2017-07-05 15:45:24 */ /* 题意: 最长连续子序列的长度 思路:线段树的区间set问题 错误:离散化出了问题,如果单纯的去重,会产生这种错误: input 2 1 3 w 5 5 w exception output: 1 5 right output: 1 3 所以离散化的时候要改进: 数据进行离散化的时候,开区间离散化端点,闭区间一般用两个点离散一个端点.例如: 开区间 [1.5] 实际的离散化之后应该是 [ (1,2) , (4,5) ]. */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <stack> #include <queue> #include <set> #include <time.h> #define LL long long #define MAXN 50000+5 #define lson i*2,l,m #define rson i*2+1,m+1,r using namespace std; int n; LL l[MAXN],r[MAXN]; char str[MAXN][2]; LL X[MAXN*2]; int len; int k; int cover[MAXN*2]; int setd[MAXN*8]; void pushup(int i,int l,int r){ if(setd[i*2]==-1||setd[i*2+1]==-1){ setd[i]=-1; }else if(setd[i*2]!=setd[i*2+1]){ setd[i]=-1; }else { setd[i]=setd[i*2]; } } void pushdown(int i,int l,int r){ if(setd[i]!=-1){ setd[i*2]=setd[i*2+1]=setd[i]; setd[i]=-1; } } void build(int i,int l,int r){ setd[i]=1; if(l==r) return ; int m=l+(r-l)/2; build(lson); build(rson); } void update(int ql,int qr,int val,int i,int l,int r){ if(ql<=l&&r<=qr){ setd[i]=val; pushdown(i,l,r); return ; } if(setd[i]==val) return ;//没有继续更新的必要 if(l==r) return ; pushdown(i,r,l); int m=l+(r-l)/2; if(m>=ql) update(ql,qr,val,lson); if(m<=qr) update(ql,qr,val,rson); // pushup(i,l,r); } void query(int ql,int qr,int i,int l,int r){ if(setd[i]!=-1){ for(int j=l;j<=r;j++){ cover[j]=setd[i]; } return ; } int m=l+(r-l)/2; if(m>=ql) query(ql,qr,lson); if(m<=qr) query(ql,qr,rson); } int findx(LL key){ int l=1,r=k,mid; while(l<=r){ mid=l+(r-l)/2; if(X[mid]==key){ return mid; }else if(X[mid]>key){ r=mid-1; }else{ l=mid+1; } } return -1; } void init(){ len=0; k=1; memset(cover,1,sizeof cover); } int main(){ // freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF){ init(); for(int i=0;i<n;i++){ scanf("%lld%lld%s",&l[i],&r[i],str[i]); X[++len]=l[i]; X[++len]=r[i]; } //处理开区间 sort(X+1,X+len+1); int t=len; for(int i=1;i<=t;i++){ if(X[i]-X[i-1]>1) X[++len]=X[i-1]+1; if(X[i]-X[i-1]>2) X[++len]=X[i]-1; } //去重 sort(X+1,X+len+1); for(int i=2;i<=len;i++){ if(X[i]!=X[i-1]){ X[++k]=X[i]; } } // for(int i=1;i<=k;i++){ // cout<<X[i]<<" "; // }cout<<endl; // cout<<"k="<<k<<endl; build(1,1,k); for(int i=0;i<n;i++){ int fl=findx(l[i]); int fr=findx(r[i]); if(str[i][0]=='w') update(fl,fr,0,1,1,k); else update(fl,fr,1,1,1,k); } // cout<<"ok"<<endl; query(1,k,1,1,k);//更新到cover数组中 // for(int i=1;i<=k;i++){ // cout<<cover[i]<<" "; // }cout<<endl; LL _max=0,_maxl,_maxr; int i=1; while(i<=k){ if(cover[i]==0){//白色气球 int j=i+1; while(cover[j]==0&&j<=k) j++; // cout<<X[j-1]<<" "<<X[i]<<endl; if(X[j-1]-X[i]+1>_max){ _max=X[j-1]-X[i]+1; _maxl=X[i]; _maxr=X[j-1]; } i = j; }else{ i++; } // cout<<_max<<endl; } if(_max==0){ puts("Oh, my god"); }else{ printf("%lld %lld\n",_maxl,_maxr); } } return 0; }
我每天都在努力,只是想证明我是认真的活着.