• [20200729NOIP提高组模拟T2]学数数——坎坷


    题目大意:

    ​ 古今序列者,长皆(n)矣.今有一序列,其长亦若此,名之曰(a).世人皆知其连续子序列之数为(frac{n(n+1)}{2})矣.现有一士,欲取之最大值于各连续子序列也.今用此(frac{n(n+1)}{2})值,构建新序列.序列,操作之本源也.于是生操作几许.予君一数(k),试问新序列中大于/小于/等于k之数有几何?

    solution:

    ​ 调了好久好久好久的bug(泪).此题不难想到线段树维护.首先将序列离散,然后开两棵线段树维护每个位置(x)左右小于等于(a[x])的连续序列长(count[x][0],count[x][1]),为防止重复,左闭右开即可.不难发现,该节点对新序列的贡献为((count[x][0]+1) cdot (count[x][1]+1)),然后对于查询操作,再开一棵线段树维新序列即可.

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<map>
    #define R register
    #define next kdjadskfj
    #define debug puts("mlg")
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    inline ll read();
    inline void write(ll x);
    inline void writeln(ll x);
    inline void writesp(ll x);
    ll n,Q;
    ll a[610000],b[620000];
    ll q;
    ll dat[6100000];
    ll type[610000],que[610000];
    ll Dat[6100000],used[620000];
    ll Count[620000][2];
    inline void Update(ll p,ll l,ll r,ll k){
    	if(l==r){Dat[p]=used[k];return;}
    	ll mid=l+r>>1;
    	if(k<=mid) Update(p<<1,l,mid,k);
    	else Update(p<<1|1,mid+1,r,k);
    	Dat[p]=max(Dat[p<<1],Dat[p<<1|1]);
    }
    
    inline ll Query(ll p,ll l,ll r,ll u,ll v){
    //	if(u>v) return 0;
    	if(!Dat[p]||(u<=l&&r<=v)) return Dat[p];
    	ll mid=l+r>>1,Ans=0;
    	if(u<=mid) Ans=max(Ans,Query(p<<1,l,mid,u,v));
    	if(v>mid) Ans=max(Ans,Query(p<<1|1,mid+1,r,u,v));
    	return Ans;
    }
    
    inline void update(ll p,ll l,ll r,ll k,ll val){
    	if(l==r){dat[p]+=val;return;}
    	ll mid=l+r>>1;
    	if(k<=mid) update(p<<1,l,mid,k,val);
    	else update(p<<1|1,mid+1,r,k,val);
    	dat[p]=dat[p<<1]+dat[p<<1|1];
    }
    
    inline ll query(ll p,ll l,ll r,ll u,ll v){
    	if(!dat[p]||(u<=l&&r<=v)) return dat[p];
    	ll mid=l+r>>1,Ans=0;
    	if(u<=mid) Ans+=query(p<<1,l,mid,u,v);
    	if(v>mid) Ans+=query(p<<1|1,mid+1,r,u,v);
    	return Ans;
    }
    
    inline void solve2(){
    	for(R ll i=1;i<=n;i++){
    //		update(1,1,q,a[i],i-Query(1,1,q,a[i]+1,q)-1);
    		Count[i][0]=i-Query(1,1,q,a[i],q)-1;
    		used[a[i]]=i;
    		Update(1,1,q,a[i]);
    	}
    		memset(used,0,sizeof used);
    		memset(Dat,0,sizeof Dat);
    	for(R ll i=n;i>=1;i--){
    //		update(1,1,q,a[i],(n-i+1)-Query(1,1,q,a[i]+1,q)-1);
    		Count[i][1]=(n-i+1)-Query(1,1,q,a[i]+1,q)-1;
    		used[a[i]]=n-i+1;
    		Update(1,1,q,a[i]);
    	}
    	for(R ll i=1;i<=n;i++){
    		update(1,1,q,a[i],(Count[i][0]+1)*(Count[i][1]+1));
    	}
    }
    
    inline void solve1(){
    	for(R ll i=1;i<=n;i++){
    		ll maxn=0;
    		for(R ll j=i;j<=n;j++){
    			maxn=max(maxn,a[j]);
    			update(1,1,q,maxn,1);
    		}
    	}
    }
    
    inline void work(){
    	for(R ll i=1;i<=Q;i++){
    		if(type[i]==1){
    			if(que[i]==q) writeln(0);
    			else writeln(query(1,1,q,que[i]+1,q));
    			continue;	
    		}
    		if(type[i]==2){
    			writeln(query(1,1,q,que[i],que[i]));
    			continue;
    		}
    		if(type[i]==3){
    			if(que[i]==1) writeln(0);
    			else writeln(query(1,1,q,1,que[i]-1));
    			continue;
    		}
    	}
    }
    
    int main(){
    	freopen("jxthree.in","r",stdin);
    	freopen("jxthree.out","w",stdout);
    	n=read();Q=read();
    	for(R ll i=1;i<=n;i++) a[i]=b[i]=read();
    	for(R ll i=1;i<=Q;i++){
    		char wn=getchar();
    		while(wn!='>'&&wn!='<'&&wn!='=') wn=getchar();
    		type[i]=((wn=='>')?1:((wn=='=')?2:3));
    		b[n+i]=que[i]=read();
    	}
    	sort(b+1,b+n+Q+1);
    	q=unique(b+1,b+Q+n+1)-b-1;
    	for(R ll i=1;i<=n;i++){
    		a[i]=lower_bound(b+1,b+q+1,a[i])-b;
    	}
    	for(R ll i=1;i<=Q;i++){
    		que[i]=lower_bound(b+1,b+q+1,que[i])-b;
    	}
    //	if(n<=5000){
    //		solve1();
    //		work();
    //		return 0;
    //	}
    	solve2();
    	work();
    }
    inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
    inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
    inline void writesp(ll x){write(x);putchar(' ');}
    inline void writeln(ll x){write(x);putchar('
    ');}
    
  • 相关阅读:
    大神语录1 如何滑动fragmentmanager里面一个fragment里面的viewgroup---dispatchTouchEvent 、onInterceptTouchEvent 、onTouchEvent
    转载-好的简历
    安卓开发8- 安卓开源项目整理github
    安卓开发7-网络通信-如何使用webservice
    安卓开发6 -Viewpager+fragment更新数据
    leetcode rotatenumber
    Java程序执行时间的简单方法
    LeetCode happyint
    安卓开发5-fragment和activity
    [转]深入理解AsyncTask的工作原理
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/13398885.html
Copyright © 2020-2023  润新知