Zoj 3581 離散化

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4383

題意很簡單:有兩根一樣長(1000W)的繩子,第一條繩子有n1(10W)個區間的缺陷,第二條繩子有n2(10W)個區間的缺陷,兩條繩子粘在一起,求只有一次缺陷的最長區間~

比賽的時候分析直接暴力肯定會超時 O_O,然後覺得肯定要用線段樹+離散化,可惜線段樹不會寫,於是放棄了*_*賽後別人說純暴力就能過,還不信,特地去寫了一下。

#include<stdio.h>
#include<string.h>
const int MAXN = 10000001;
int flag[MAXN];
int max_len(int n)
{
	int re =0,num;
	for(int i=0;i<n;)
	{
		num = 0;
		while(flag[i]==1)
		{
			num++;
			i++;
		}
		if(num>re)
			re = num;
		i++;
	}
	return re;
}
int main()
{
	int n,n1,n2,x,y;
	while(scanf("%d%d%d",&n,&n1,&n2)!=EOF)
	{
		memset(flag,0,sizeof(flag));
		int t = n1+n2;
		for(int i=0;i<t;i++)
		{
			scanf("%d%d",&x,&y);
			for(int j=x;j<=y;j++)
				flag[j]++;
		}
		printf("%d\n",max_len(n));
	}
	return 0;
}
其實仔細分析了一下,若數據保證輸入的區間不會重複的話,賦值+查找最多複雜度也纔是3000W,額。。當時傻了。。

直接暴力交了之後是600ms,於是覺得可以離散化。時間是300多。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn=100001;
struct node
{
	int x,y;
}oo[2*maxn],que[4*maxn];
int tt[4*maxn],flag[4*maxn];
int deal(int n)
{
	int i,re=0;
	que[re].x = tt[0];
	que[re++].y = tt[0];
	for(i=1;i<n;i++)
	{
		if(tt[i]-tt[i-1]>1)
		{
			que[re].x = tt[i-1] + 1;
			que[re++].y = tt[i] -1;
		}
		que[re].x = tt[i];
		que[re++].y = tt[i];
	}
	return re;
}
int search(int val,int len)
{	
	int l,r,mid;
	l = 0;
	r = len;
	while(l<=r)
	{
		mid = ((l+r)>>1);
		if(que[mid].x == val)
			return mid;
		else if(que[mid].x >val)
			r = mid - 1;
		else
			l = mid + 1;
	}
	return -1;
}
void sum(int a)
{
	int i,re=0,num;
	for(i=0;i<a;)
	{
		num = 0;
		while(flag[i] == 1)
		{
			num += (que[i].y - que[i].x +1);
			i++;
		}
		if(num>re)
			re = num;
		i++;
	}
	printf("%d\n",re);
}
int main()
{
	int m,n1,n2,i,num;
	while(scanf("%d%d%d",&m,&n1,&n2)!=EOF)
	{
		int tmp = n1+n2;
		num=0;
		for(i=0;i<tmp;i++)
		{
			scanf("%d%d",&oo[i].x,&oo[i].y);
			tt[num++] = oo[i].x;
			tt[num++] = oo[i].y;
		}
		sort(tt,tt+num);
		int cnt = unique(tt,tt+num)-tt;//tt中不相同點的個數
		int a = deal(cnt);//對tt中的點進行座標離散化後區間個數
		memset(flag,false,sizeof(flag));
		for(i=0;i<tmp;i++)//賦值
		{
			int l = search(oo[i].x,a);
			int r = search(oo[i].y,a);
 			for(int j=l;j<=r;j++)
				flag[j]++;
		}
		sum(a);//統計
	}
	return 0;
}
其實我覺得若是沒有那個區間不重複的條件的話,這兩種方法應該都會超,隊員寫了線段樹+離散化,一直MLE,可能寫搓了,求線段樹+離散化!!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章