亂搞

對於一個數字序列。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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章