[POI2011]LIZ-Lollipop

Posted wendigo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POI2011]LIZ-Lollipop相关的知识,希望对你有一定的参考价值。

[POI2011]LIZ-Lollipop

前置知识:

破脑术开脑洞。


[POI2011]LIZ-Lollipop

给定一个长度为 (n) 的序列 (a{n}(a_iin{1,2}))(m) 次询问求 (k) 是否可以表示成连续某段序列 (a_Lsim a_R) 的和。如果可以,输出 (L)(R)。否则,输出 ( exttt{NIE})。(注:读入序列用字符串,( exttt{T}) 表示 (2)( exttt{W}) 表示 (1))。

数据范围:(1le n,mle 10^6)(1le kle 2 imes 10^6)


如果不是思维难度的原因,这题是橙色的吧。


首先想到区间和就要先把前缀和算出来。

逆推做。如果有一个区间 ([L,R]) 的和为 (x),那么如何得出和为 (x-2) 的区间呢

  1. 满足 (a_L=2)(a_R=2),所以和为 (x-2) 的区间是 ([a_L+1,a_R])([a_L,a_R-1])

  2. 否则肯定 (a_L=a_R=1),那么和为 (x-2) 的区间就是 ([a_l+1,a_R-1])

所以只需要找出最大的奇数区间和 (x) 和最大的偶数区间和 (x) 即可。

然后逆推别的,可以循环或者递归,至于找最大奇偶数区间和,就不必多说了。


( exttt{code})

#include <bits/stdc++.h>
using namespace std;

//&Start
#define lng long long
#define lit long double
#define re register
#define kk(i,n) " 
"[i==n]
const int inf=0x3f3f3f3f;
const lng Inf=0x3f3f3f3f3f3f3f3f;

//&Data
const int N=1e6;
int n,m,a[N+10],mo=-1,me=-1;
int l[(N<<1)+10],r[(N<<1)+10],sum[N+10];
//l[i] 表示区间和为 i 的区间左端点,r[i] 表示右端点(不开双倍空间也能得不少分吧)
char c[N+10];

//&Solve
void solve(int x){ //循环实现逆推
    if(x<=2) return;
    if(a[l[x]]==2) l[x-2]=l[x]+1,r[x-2]=r[x];
    else if(a[r[x]]==2) l[x-2]=l[x],r[x-2]=r[x]-1;
    else l[x-2]=l[x]+1,r[x-2]=r[x]-1;
    solve(x-2);
}

//&Main
int main(){
    memset(l,-1,sizeof l);
    memset(r,-1,sizeof r);
    scanf("%d%d%s",&n,&m,c+1);
    //-----------------魔芋分割线---------------------------
    for(int i=1;i<=n;i++) a[i]=(c[i]=='T'?2:1);
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]; //求前缀和
    //-----------------魔芋分割线---------------------------
    if(sum[n]&1) mo=sum[n],l[mo]=1,r[mo]=n;
    else me=sum[n],l[me]=1,r[me]=n; //因为所有数的和肯定是该奇偶性下最大的
    // printf("varque %d %d
",mo,me);
    //-----------------魔芋分割线---------------------------
    int lf=-1,ri=-1;
    for(int i=1;i<=n;i++)if(a[i]==1){lf=i;break;}
    for(int i=n;i>=1;i--)if(a[i]==1){ri=i;break;}//找1,得出另外奇偶性下最大的区间和
    //-----------------魔芋分割线---------------------------
    int tmp=-1,lt=-1,rt=-1;
    if(lf!=-1&&sum[n]-sum[lf]>tmp)
        tmp=sum[n]-sum[lf],lt=lf+1,rt=n;
    if(ri!=-1&&sum[ri-1]>tmp)
        tmp=sum[ri-1],lt=1,rt=ri-1;
    //-----------------魔芋分割线---------------------------
    if(sum[n]&1) me=tmp,l[me]=lt,r[me]=rt;
    else mo=tmp,l[mo]=lt,r[mo]=rt;
    // printf("varque %d %d
",mo,me);
    //-----------------魔芋分割线---------------------------
    solve(mo); //逆推
    solve(me);
    //-----------------魔芋分割线---------------------------
    for(int i=1,x;i<=m;i++){
        scanf("%d",&x);
        if(l[x]==-1&&r[x]==-1) puts("NIE"); //没有方案
        else printf("%d %d
",l[x],r[x]); //输出
    }
    return 0;
}

祝大家学习愉快!

以上是关于[POI2011]LIZ-Lollipop的主要内容,如果未能解决你的问题,请参考以下文章

POI2011 棒棒糖 Lollipop

BZOJ2212 [Poi2011]Tree Rotations 线段树合并 逆序对

bzoj 2212 : [Poi2011]Tree Rotations (线段树合并)

java poi xwpf操作word生成一个表格怎么合并单元格,求大神指导!

雷林鹏分享:Apache POI电子表格/Spreadsheet

雷林鹏分享:Apache POI电子表格/Spreadsheet