【set】【可持久化Trie】The 16th UESTC Programming Contest Preliminary K - Will the circle be broken

題意:You are given an array A of N non-negative integers and an integer M.atom

Find the number of pair(i,j) such that 1ijN and min(Ai,Ai+1,...,Aj)(AiAi+1...Aj)M.spa

先用把數字從小到大依次插入,用個set預處理出每一個最小值控制的子區間的範圍,對於大小相同的數,靠左的數優先。orm

而後對於每一個子區間,最小值將它劃分紅左右兩段,枚舉較短的那段,在較長的那段中用可持久化Trie查詢知足條件的對數。前綴異或和別忘了處理,很經典了。xml

就是設M/min(Ai,Ai+1,...,Aj)爲W,每次向左右兒子查詢,若是W的這位是零,那就不累計答案,直接朝零(這裏指異或上左端點的前綴和之後的零)走;若是W的這位是一,那就統計上零(這裏指異或上左端點的前綴和之後的零)的子樹的答案,而後朝一走。別忘了到葉子之後還要在累計一次。(葉子必然知足條件,能夠累計。)blog

#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
typedef set<int>::iterator ITER;
typedef long long ll;
int n;
ll m,a[100005];
int b[100005],lb[100005],ub[100005];
int w,xors[100005];
bool cmp(const int &x,const int &y){
	return (a[x]!=a[y] ? a[x]<a[y] : x<y);
}
ll ans;
#define N 100005
#define MAXBIT 31
int root[N],ch[N*(MAXBIT+1)][2],sz[N*(MAXBIT+1)],tot;
void add(int now,int W)
{
    int old=root[now-1];
    root[now]=++tot;
    now=root[now];
    for(int i=MAXBIT;i>=1;--i)
      {
        int Bit=((W>>(i-1))&1);
        sz[now]=sz[old]+1;
        ch[now][Bit^1]=ch[old][Bit^1];
        ch[now][Bit]=++tot;
        now=ch[now][Bit];
        old=ch[old][Bit];
      }
    sz[now]=sz[old]+1;
}
void query(int bef,int L,int R,int W,int fl)
{
    L=root[L];R=root[R+1];
    for(int i=MAXBIT;i>=1;--i){
        int Bit=(W>>(i-1)&1);
        if(Bit==1){
        	if((xors[bef-fl]>>(i-1)&1)==1){
        		ans+=(ll)(sz[ch[R][1]]-sz[ch[L][1]]);
        		R=ch[R][0];
        		L=ch[L][0];
        	}
        	else{
        		ans+=(ll)(sz[ch[R][0]]-sz[ch[L][0]]);
        		R=ch[R][1];
        		L=ch[L][1];
        	}
        }
        else{
        	if((xors[bef-fl]>>(i-1)&1)==1){
        		R=ch[R][1];
        		L=ch[L][1];
        	}
        	else{
        		R=ch[R][0];
        		L=ch[L][0];
        	}
        }
    }
	ans+=(ll)(sz[R]-sz[L]);
}
int main(){
	//freopen("f.in","r",stdin);
	scanf("%d%lld",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%lld",&a[i]);
		xors[i]=(xors[i-1]^a[i]);
	}
	for(int i=1;i<=n;++i){
		b[i]=i;
	}
	sort(b+1,b+n+1,cmp);
	set<int> S;
	for(int i=1;i<=n;++i){
		ITER it=S.lower_bound(b[i]);
		if(it!=S.end()){
			ub[b[i]]=((*it)-1);
		}
		else{
			ub[b[i]]=n;
		}
		if(it==S.begin()){
			lb[b[i]]=1;
		}
		else{
			--it;
			lb[b[i]]=((*it)+1);
		}
		S.insert(b[i]);
	}
	add(1,0);
	for(int i=1;i<=n;++i){
		add(i+1,xors[i]);
	}
	for(int i=1;i<=n;++i){
		if(m/a[i]>=(1ll<<31)){
			ans+=(ll)(i-lb[i]+1)*(ll)(ub[i]-i+1);
			continue;
		}
		w=(int)(m/a[i]);
		if(i-lb[i]<=ub[i]-i){
			for(int j=lb[i];j<=i;++j){
				query(j,i,ub[i],w,1);
			}
		}
		else{
			for(int j=i;j<=ub[i];++j){
				query(j,lb[i]-1,i-1,w,0);
			}
		}
	}
	printf("%lld\n",ans);
	return 0;
}
相關文章
相關標籤/搜索