zoukankan      html  css  js  c++  java
  • BZOJ 3956: Count 主席树 可持久化线段树 单调栈

    https://www.lydsy.com/JudgeOnline/problem.php?id=3956

    从描述可以得到性质: 每个好点对 ( 除了差值为1的好点对 ) 中间的数 ( i , j ) 一定有一个最大值, 视这个值控制这个好点对, 那么每个值最多只控制一个好点对. 

    然后我们就可以通过单调栈 ( 求出lp[i]左边第一个大于i的数的坐标, rp[i]右边第一个大于i的数的坐标, lf[i]左边第一个大于等于i的数的坐标 (为避免重复只统计有重复区间的值里的最左边一个,即lp=lf则不统计) )  找到每个点控制的好点对 ( 也就是找到所有好点对 ) . 

    然后用主席树维护询问(对每个l建r作为查找值的树). 

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 const int maxn=300010;
     8 int n,m,T;
     9 int a[maxn]={},sta[maxn]={},tail=0;
    10 int lp[maxn]={},rp[maxn]={},lf[maxn]={},rt[maxn]={};
    11 int lc[maxn*40]={},rc[maxn*40]={},siz[maxn*40]={},tot=0;
    12 struct nod{
    13     int x,y;
    14 }e[maxn];int cnt=0;
    15 bool mcmp(nod aa,nod bb){ return aa.x<bb.x; }
    16 int read(){
    17     int w=0,f=1;char ch=getchar();
    18     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    19     while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
    20     return w*f;
    21 }
    22 void build(int &x,int y,int l,int r,int z){
    23     x=++tot;siz[x]=siz[y]+1;lc[x]=lc[y];rc[x]=rc[y];
    24     if(l==r)return;
    25     int mid=(l+r)/2;
    26     if(z<=mid)build(lc[x],lc[y],l,mid,z);
    27     else build(rc[x],rc[y],mid+1,r,z);
    28 }
    29 int getsum(int x,int y,int l,int r,int z,int t){
    30     if(z<=l&&r<=t)return siz[y]-siz[x];
    31     int mid=(l+r)/2,ans=0;
    32     if(z<=mid)ans=getsum(lc[x],lc[y],l,mid,z,t);
    33     if(t>mid)ans+=getsum(rc[x],rc[y],mid+1,r,z,t);
    34     return ans;
    35 }
    36 inline void fir(){
    37     int i;
    38     a[0]=a[n+1]=(1<<30);
    39     for(i=1;i<=n;++i){
    40         while(a[sta[tail]]<=a[i])tail--;
    41         lp[i]=sta[tail];sta[++tail]=i;
    42     }
    43     sta[0]=n+1;tail=0;
    44     for(i=n;i>0;--i){
    45         while(a[sta[tail]]<=a[i])tail--;
    46         rp[i]=sta[tail];sta[++tail]=i;
    47     }
    48     tail=0;sta[0]=0;
    49     for(i=1;i<=n;++i){
    50         while(a[sta[tail]]<a[i])tail--;
    51         lf[i]=sta[tail];sta[++tail]=i;
    52     }
    53 }
    54 inline void init(){
    55     int i,j;
    56     for(i=1;i<=n;++i){
    57         if(lp[i]&&rp[i]<=n&&lp[i]==lf[i]){//最近的比a[i]大的数与a[i]间没有与a[i]相等的数,避免重复记录
    58             e[++cnt].x=lp[i];e[cnt].y=rp[i];//lp[i]和rp[i]必须合法
    59         }
    60     }sort(e+1,e+cnt+1,mcmp);
    61     for(i=j=1;i<=n;++i){
    62         rt[i]=rt[i-1];
    63         while(j<=cnt&&e[j].x==i){build(rt[i],rt[i],1,n,e[j].y);j++;}
    64     }
    65 }
    66 int main(){
    67     int i,x,y,ans=0;
    68     n=read();m=read();T=read();
    69     for(i=1;i<=n;++i)a[i]=read();
    70     fir(); init();
    71     for(i=1;i<=m;++i){
    72         x=read();y=read();
    73         if(T){x=(x+ans-1)%n+1;y=(y+ans-1)%n+1;}
    74         if(x>y)swap(x,y);
    75         ans=getsum(rt[x-1],rt[y],1,n,x,y)+y-x;
    76         printf("%d
    ",ans);
    77     }
    78     return 0;
    79 }
    View Code

  • 相关阅读:
    Linux系统开发笔记
    软件测试 | Chrome 浏览器+Postman还能这样做接口测试 ?
    yum 在线安装 nginx
    画图3D Paint 3D工作区黑屏
    InfluxDB 存储结构、读、写
    纯前端保存下载文件到本地
    umijs 配置的一些用法和解释 记录
    mongodb在双活(主备)机房的部署方案和切换方案设计
    mongodb oplog详解和格式分析
    麒麟操作系统上安装docker并加载镜像
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8780832.html
Copyright © 2011-2022 走看看