Cod sursa(job #466853)

Utilizator AndreyPAndrei Poenaru AndreyP Data 27 iunie 2010 18:56:59
Problema Numarare Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.24 kb
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <set>
#include <algorithm>
using namespace std;
#define ll int
#define N 100005
#define C 900010
#define fs first
#define sc second
#define mp make_pair
#define K 1
#define pii pair< int,int >
int n;
int a[N];
char c[C];
ll rez;
//ll m=1099957LL;
ll m=29959;
ll p=173;
int h[2][N];
int pp[N];
set< pii > se;
inline void citire()
{
	scanf("%d\n",&n);
	fgets(c,C,stdin);
	int x=0;
	int j=0;
	bool neg=false;
	
	for(int i=1; i<=n; ++i)
	{
		if(c[j]=='-')
		{
			++j;
			neg=true;
		}
		else
			neg=false;
		x=0;
		for(; c[j]>='0' && c[j]<='9'; ++j)
			x=x*10+(c[j]-'0');
		if(neg)
			a[i]=-x;
		else
			a[i]=x;
		++j;
	}
}

inline void rezolva1()
{
	if(n==1)
	{
		printf("0\n");
		return;
	}
	int x,y;
	int cat;
	bool ok;
	int lun;
	for(int i=1; i<n; ++i)
	{
		x=i;
		y=i+1;
		cat=a[x]+a[y];
		--x;
		++y;
		++rez;
		ok=true;
		lun=1;
		for(; ok && x>0 && y<=n; --x,++y)
		{
			if(a[x]+a[y]==cat)
			{
				++rez;
				++lun;
			}
			else
				ok=false;
		}
		//printf("%d ",lun);
	}
	//printf("\n");
	
	printf("%d\n",rez);
}

inline void precalc()
{
	
	for(int i=1; i<n; ++i)
		a[i]-=a[i+1];
	int nr=0;
	set< pii >::iterator it;
	for(int i=1; i<n; ++i)
	{
		it=se.lower_bound(mp(a[i],0));
		if(it==se.end() || (it->fs)!=a[i])
		{
			++nr;
			se.insert(mp(a[i],nr));
			a[i]=nr;
			continue;
		}
		a[i]=(it->sc);
	}
	
	//for(int t=0; t<K; ++t)
	//{
		h[0][1]=a[1];
		h[1][n-1]=a[n-1];
		pp[0]=1;
		pp[1]=p;
	//}
	
	ll x;
	for(int i=2; i<n; ++i)
	{
		//for(int t=0; t<K; ++t)
		//{
			x=((ll)h[0][i-1]*p+(ll)a[i]);
			if(x>=m)
				x%=m;
			h[0][i]=(int)x;
			x=(ll)pp[i-1]*p;
			if(x>=m)
				x%=m;
			pp[i]=(int)x;
		//}
	}
	
	for(int i=n-2; i>0; --i)
	{
		//for(int t=0; t<K; ++t)
		//{
			x=((ll)h[1][i+1]*p+(ll)a[i]);
			if(x>=m)
				x%=m;
			h[1][i]=(int)x;
		//}
	}
}

inline bool eok(int i,int x,int y)
{
	int put=i-x;
	ll aux1,aux2;
	//for(int t=0; t<K; ++t)
	//{
		aux1=(ll)h[0][x-1]*(ll)pp[put];
		if(aux1>=m)
			aux1%=m;
		aux1=(ll)h[0][i-1]-aux1;
		if(aux1<0)
			aux1+=m;
		
		aux2=(ll)h[1][y+1]*(ll)pp[put];
		if(aux2>=m)
			aux2%=m;
		aux2=(ll)h[1][i+1]-aux2;
		if(aux2<0)
			aux2+=m;
		
		if(aux1!=aux2)
			return false;
	//}
	return true;
}

inline int minim(int x,int y)
{
	return ( (x<y) ? (x) : (y) );
}

inline void caut(int i)
{
	++rez;
	if(a[i-1]!=a[i+1])
	{
		//printf("1 ");
		return;
	}
	
	int lim=minim(i-1,n-i-1);
	int p=1,u=lim;
	int m;
	while(p+1<u)
	{
		m=(p+u)>>1;
		if(eok(i,i-m,i+m))
			p=m;
		else
			u=m-1;
	}
	if(p+1<=lim)
	{
		if(eok(i,i-p-1,i+p+1))
		{
			++p;
			if(p+1<=lim)
			{
				if(eok(i,i-p-1,i+p+1))
					++p;
			}
		}
	}
	
	//printf("%d ",p+1);
	rez+=(ll)p;
}
	
inline void rezolva2()
{
	precalc();
	++rez;
	++rez;
	//printf("1 ");
	for(int i=2; i+1<n; ++i)
		caut(i);
	//printf("1\n");
	
	printf("%d\n",rez);
}

int main()
{
	freopen("numarare.in","r",stdin);
	freopen("numarare.out","w",stdout);
	
	citire();
	if(n==1)
	{
		printf("0\n");
		return 0;
	}
	if(n==2)
	{
		printf("1\n");
		return 0;
	}
	//if(n<3010)
	//	rezolva1();
	//else
		rezolva2();

	return 0;
}