• NOIP模拟题 序列


    题目大意

    给定长为$n$的序列$A$,定义长为$k$的区间中位数为从小到大排完序后第$lfloorfrac{k}{2} floor$个数的大小。

    每次询问给定$l_1,r_1,l_2,r_2$有多少个子区间满足中位数$in[l_1,r_1]$长度$in[l_2,r_2]$。

    询问不超过五组。

    题解

    将问题提转化成中位数$leq K$,长度$in [l,r]$的子区件有多少个,答案相减即为最终答案。

    发现对于每一个$A_i$,若子区间内$A_ileq K$的数量至少达到区间长度的一半即可。

    那么将$A_ileq K$看做$1$,否则看做$-1$,求区间和$geq 0$,区间长度$in [l,r]$的数量即可。

    这个只需要用主席树或者删电加点的树状数组维护即可。

    复杂度$O(2nmlog n)$。

    #include<bits/stdc++.h>
    #define debug(x) cerr<<#x<<" = "<<x
    #define sp <<"  "
    #define el <<endl
    #define LL long long
    #define M 100020
    using namespace std;
    int read(){
    	int nm=0,fh=1; char cw=getchar();
    	for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
    	for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
    	return nm*fh;
    }
    int s[M],n,m,p[M],cnt,rt[M],bf[M<<2],nt[M<<2],c[M<<2];
    void ins(int pos,int dt){for(int k=pos;k<(M<<1);k=nt[k]) c[k]+=dt;}
    int qry(int pos){int tt=0;for(int k=pos;k;k=bf[k]) tt+=c[k];return tt;}
    LL solve(int Mid,int Min_len,int Max_len){
    	LL res=0;
    	memset(c,0,sizeof(c));
    	for(int i=1;i<=n;i++){
    		s[i]=(p[i]<=Mid?s[i-1]+1:s[i-1]-1);
    		int t1=i-Max_len-1,t2=i-Min_len;
    		if(t1>=0) ins(s[t1]+M,-1);
    		if(t2>=0) ins(s[t2]+M,1); res+=qry(s[i]+M);
    	}return res;
    }
    int main(){
    	n=read();
    	for(int i=1;i<(M<<2);i++) bf[i]=i-(i&-i),nt[i]=i+(i&-i);
    	for(int i=1;i<=n;i++) p[i]=read();
    	for(int T=read();T;--T){
    		int l1=read(),r1=read(),l2=read(),r2=read();
    		printf("%lld
    ",solve(r1,l2,r2)-solve(l1-1,l2,r2));
    	}
    	return 0;
    }

     

  • 相关阅读:
    加载页面遮挡耗时操作任务页面--第三方开源--AndroidProgressLayout
    【数据库】SQLite学习
    【数据库】MongoDB学习
    【英语】Bingo口语笔记(8)
    【英语】TED视频笔记
    自动关联
    HTML和URL比较
    LR回放测试脚本
    LR录制脚本IE不能打开解决方法
    LR录制测试脚本
  • 原文地址:https://www.cnblogs.com/OYJason/p/9900621.html
Copyright © 2020-2023  润新知