[POI2011]LIZ-Lollipop
Posted wendigo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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) 的区间呢:
满足 (a_L=2) 或 (a_R=2),所以和为 (x-2) 的区间是 ([a_L+1,a_R]) 或 ([a_L,a_R-1])。
否则肯定 (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的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ2212 [Poi2011]Tree Rotations 线段树合并 逆序对
bzoj 2212 : [Poi2011]Tree Rotations (线段树合并)
java poi xwpf操作word生成一个表格怎么合并单元格,求大神指导!