zoukankan      html  css  js  c++  java
  • [国家集训队2012]middle(陈立杰)

    我是萌萌的传送门

    我是另一个萌萌的传送门

    脑残错误毁一下午……

    其实题解早就烂大街了,然而很久之前我只知道是二分答案+主席树却想不出来这俩玩意儿怎么一块儿用的……今天又翻了几篇题解才恍然大悟,是把权值排序之后依次插入序列,用主席树维护连续和……(我菜爆了……= =)

    还是讲讲大体思路吧,首先二分答案M,把>=M的元素标为1,<M的标为-1,然后判定满足条件的最大子串和是否>=0,是则说明判定标准可行,否则不可行,调整下一次二分即可。但是直接暴力标记肯定会T,所以尝试对所有判定标准维护线段树来求最大子串和,然而内存开不下……考虑到如果把元素依次插入的话每次只会修改一个值,那么就把元素排序后依次插入线段树中,可持久化压内存即可。

    一点细节:

    鉴于子序列中间那段是肯定会用到的,所以直接拆成三段,前一段求最大后缀和,中间直接求和,后一段求最大前缀和,合并即可。因为最大前缀/后缀和是非严格最大(可以一个都不选),所以需要把b和c归到中间那段(保证一定会用上)。

    贴个bzoj的代码:

      1 /**************************************************************
      2     Problem: 2653
      3     User: hzoier
      4     Language: C++
      5     Result: Accepted
      6     Time:936 ms
      7     Memory:101108 kb
      8 ****************************************************************/
      9  
     10 #include<cstdio>
     11 #include<cstring>
     12 #include<algorithm>
     13 using namespace std;
     14 const int maxn=20010;
     15 struct node{
     16     int sum,prefix,suffix;
     17     node *lc,*rc;
     18     void refresh(){
     19         sum=lc->sum+rc->sum;
     20         prefix=max(lc->prefix,lc->sum+rc->prefix);
     21         suffix=max(rc->suffix,rc->sum+lc->suffix);
     22     }
     23 }null[maxn<<8],*ptr=null;
     24 struct A{
     25     int d,id;
     26     bool operator<(const A &a)const{return d<a.d;}
     27 }a[maxn];
     28 void build(int,int,node*&);
     29 void modify(int,int,node*&,node*&);
     30 void qsum(int,int,node*);
     31 void qprefix(int,int,node*);
     32 void qsuffix(int,int,node*);
     33 node *root[maxn];
     34 int n,m,x,d,s,t,q[5],tmp,sum,ans,lastans=0,L,R,M;
     35 int main(){
     36     null->lc=null->rc=null;
     37     null->sum=null->prefix=null->suffix=0;
     38     scanf("%d",&n);
     39     fill(root,root+n+1,(node*)null);
     40     build(1,n,root[0]);
     41     for(int i=1;i<=n;i++){
     42         scanf("%d",&a[i].d);
     43         a[i].id=i;
     44     }
     45     sort(a+1,a+n+1);
     46     for(int i=1;i<=n;i++){
     47         x=a[i].id;
     48         modify(1,n,root[i],root[i-1]);
     49     }
     50     scanf("%d",&m);
     51     while(m--){
     52         for(int i=0;i<4;i++){
     53             scanf("%d",&q[i]);
     54             q[i]+=lastans;q[i]%=n;q[i]++;
     55         }
     56         sort(q,q+4);
     57         L=1;R=n;
     58         while(L<=R){
     59             M=(L+R)>>1;
     60             ans=0;
     61             s=q[1];t=q[2];
     62             qsum(1,n,root[M-1]);
     63             s=q[0];t=q[1]-1;
     64             sum=tmp=0;
     65             if(s<=t)qsuffix(1,n,root[M-1]);
     66             ans+=sum;
     67             s=q[2]+1;t=q[3];
     68             sum=tmp=0;
     69             if(s<=t)qprefix(1,n,root[M-1]);
     70             ans+=sum;
     71             if(ans>=0)L=M+1;
     72             else R=M-1;
     73         }
     74         printf("%d
    ",lastans=a[R].d);
     75     }
     76     return 0;
     77 }
     78 void build(int l,int r,node *&rt){
     79     rt=++ptr;
     80     rt->sum=rt->prefix=rt->suffix=r-l+1;
     81     if(l==r){
     82         rt->lc=rt->rc=null;
     83         return;
     84     }
     85     int mid=(l+r)>>1;
     86     build(l,mid,rt->lc);
     87     build(mid+1,r,rt->rc);
     88 }
     89 void modify(int l,int r,node *&rt,node *&pr){
     90     *(rt=++ptr)=*pr;
     91     if(l==r){
     92         rt->sum=-1;
     93         rt->prefix=rt->suffix=0;
     94         return;
     95     }
     96     int mid=(l+r)>>1;
     97     if(x<=mid)modify(l,mid,rt->lc,pr->lc);
     98     else modify(mid+1,r,rt->rc,pr->rc);
     99     rt->refresh();
    100 }
    101 void qsum(int l,int r,node *rt){
    102     if(s<=l&&t>=r){
    103         ans+=rt->sum;
    104         return;
    105     }
    106     int mid=(l+r)>>1;
    107     if(s<=mid)qsum(l,mid,rt->lc);
    108     if(t>mid)qsum(mid+1,r,rt->rc);
    109 }
    110 void qprefix(int l,int r,node *rt){
    111     if(s<=l&&t>=r){
    112         sum=max(sum,tmp+rt->prefix);
    113         tmp+=rt->sum;
    114         return;
    115     }
    116     int mid=(l+r)>>1;
    117     if(s<=mid)qprefix(l,mid,rt->lc);
    118     if(t>mid)qprefix(mid+1,r,rt->rc);
    119 }
    120 void qsuffix(int l,int r,node *rt){
    121     if(s<=l&&t>=r){
    122         sum=max(sum,tmp+rt->suffix);
    123         tmp+=rt->sum;
    124         return;
    125     }
    126     int mid=(l+r)>>1;
    127     if(t>mid)qsuffix(mid+1,r,rt->rc);
    128     if(s<=mid)qsuffix(l,mid,rt->lc);
    129 }
    View Code

    话说这份代码跑得还挺快,哈哈……

    写题过程中出了两个脑残错误,两个多小时就这么搭进去了……

    1.如果序列长度为偶数,按题意中位数应为中间的两个数中较大的那个,然而我一开始读成了较小的那个,然后就死活弄不清脑子一片混乱……

    2.注意到求最大后缀和最后一句if(s<=mid)了没……一开始写成了if(t<=mid),然后澄清完了题意还各种跟暴力拍不上,我特么都快崩溃了……后来发现是这个脑残错误,我只想说: $%*&$^%&#$%!@&#@^&*!%$^#@%*……

    看看这惨烈的提交记录……

    下次写题一定要先澄清题意……脑残怎么治啊……

  • 相关阅读:
    java加密解密用法
    进程和线程
    office使用技巧
    apktool+dex2jar+jd_gui
    shell编程学习
    编程常犯的错误
    编程语言学习清单
    使用github托管自己的项目
    c# 异常 的 异想
    DNLA自学(一) UPnP设备发现
  • 原文地址:https://www.cnblogs.com/hzoier/p/6266078.html
Copyright © 2011-2022 走看看