乱搞

对于一个数字序列。a1~n判断是否任意一个连续子序列都存在一个数字只出现了一次  ai<=10^9, n<=20^5

非常扯犊子的题目.

这题看了思路其实很简单。。。但是为什么要双向同时查找呢。据说这就相当于。启发式合并的逆过程所以就nlogn了。。我不会告诉你其实每次随机一边开始扫也是一样的复杂度。。。

#include <cstdio>  
#include <cmath>  
#include <ctime>  
#include <string>  
#include <cstring>  
#include <cstdlib>  
#include <iostream>  
#include <algorithm>  
  
#include <vector>  
#include<map>

#define forup(i,a,b) for(int i=(a);i<=(b);i++)  
#define fordown(i,a,b) for(int i=(a);i>=(b);i--)  
  
#define maxn 2000005 

using namespace std;  
 
  
template<class T> inline  
void read(T& num){   num = 0; bool f = true;char ch = getchar();   while(ch < '0' || ch > '9') { if(ch == '-') f = false;ch = getchar();}  while(ch >= '0' && ch <= '9') {num = num * 10 + ch - '0';ch = getchar();}   num = f ? num: -num; } 


int T,n;
int a[maxn];
int nxt[maxn],pre[maxn];
map<int,int> num;
bool  solve(int L,int R)
{ if(L>=R)  return true; 
 int l=L,r=R;
   while(((nxt[l]<=R&&nxt[l]!=0)||(pre[l]>=L&&pre[l]!=0))&&((nxt[r]<=R&&nxt[r]!=0)||(pre[r]>=L&&pre[r]!=0)))
     {l++;r--;
      if(l>r) return false; 
	 }
	 if((nxt[l]>R||nxt[l]==0)&&(pre[l]<L||pre[l]==0)) return solve(L,l-1)&&solve(l+1,R);
	 else  return solve(L,r-1)&&solve(r+1,R);
}

int main()
{cin>>T;
 while(T--)
  {read(n);//forup(i,0,n+1)  { pre[i]=0,nxt[i]=0;}
  num.clear();  
     forup(i,1,n) {read(a[i]);pre[i]=num[a[i]];num[a[i]]=i;  }
      num.clear();
	  fordown(i,n,1)  {nxt[i]=num[a[i]];num[a[i]]=i;}
  if(solve(1,n))  printf("yes\n");else  printf("no\n");
  }
	
	
	
	
	return 0;
 } 



发布了56 篇原创文章 · 获赞 0 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章