题解 P3514 【[POI2011]LIZ-Lollipop】
LightningUZ · · 题解
很巧妙的思维题。
题意是这样的,给你一个串,只有 T 和 W。令 T=2,W=1,将其变成数字串。然后每次给一个
判断是否有解
重要结论1:如果
证:假设
[l,r] 区间的和是k 。
如果这个区间的两边 (a[l] ,a[r] ) 中有一个是2 ,那么把这个去掉 (变成l,r-1 或l+1,r ),那就有k-2 了
否则它两边就都是1 。把两边都去掉,那就有k-2 了。 综上,我们一定有k-2 。
证毕
然后就好做了:找到最大的奇数,最大的偶数;对于奇数,判断它是否小于最大的奇数,偶数同理。
如何找到最大的奇数/偶数?
设
显然
重要结论2:只要枚举左边/右边删连续的就行。
证: 假设我们非要删掉两边才能使答案最优
如果两边中有一边是偶数,那偶数这边不删,肯定更优
否则,两边都是奇数。两边都不删,肯定更优
注:“更优”表示的是,模2 余数不变,并且和更大
证毕
输出解
设
首先,
然后,我们在枚举删前后,求出
对于答案区间
然后就显然可以推出所有的答案区间了。
simple 的代码
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define N 4000006
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)
#define Tra(i,u) for(int i=G.Start(u),v=G.To(i);~i;i=G.Next(i),v=G.To(i))
#define p_b push_back
#define sz(a) ((int)a.size())
#define all(a) a.begin(),a.end()
#define iter(a,p) (a.begin()+p)
int I() {char c=getchar(); int x=0; int f=1; while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar(); while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return (x=(f==1)?x:-x);}
void Rd(int cnt,...) {va_list args;va_start(args,cnt); F(i,1,cnt) {int* x=va_arg(args,int*);(*x)=I();} va_end(args);}
void RA(int *a,int n) {int *p=(a+1); F(i,1,n) {(*p)=I();++p;}}
int n,m;
char ss[N]; int a[N];
void Input()
{
Rd(2,&n,&m); scanf("%s",ss+1);
F(i,1,n) a[i]=(ss[i]=='T')?2:1;
}
int s[N];
int Max[2]; int l[N],r[N];
void up(int a,int ll,int rr)
{
if (a>Max[a%2]) {Max[a%2]=a; l[a]=ll; r[a]=rr; }
}
void get(int &l,int &r,int pl,int pr)
{
if (pl==0 and pr==0) return;
l=pl,r=pr;
if (a[pl]==2) ++l;
else if (a[pr]==2) --r;
else ++l,--r;
}
void Soviet()
{
F(i,1,n) s[i]=s[i-1]+a[i];
F(i,1,n-1) {up(s[n]-s[i],i+1,n); up(s[i],1,i);} up(s[n],1,n);
// 枚举删左边/右边,以及全选
D(i,2*n,1) get(l[i],r[i],l[i+2],r[i+2]);
// 继承
F(i,1,m)
{
int k=I();
if (k>Max[k%2]) puts("NIE");
else printf("%d %d\n",l[k],r[k]);
}
}
void IsMyWife()
{
Input();
Soviet();
}
}
#undef int //long long
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();
return 0;
}