【洛谷3514】[POI2011] LIZ-Lollipop(构造)

点此看题面

  • 给定一个长度为(n)的只包含(1)(2)的序列。
  • (q)次询问,每次要求找到一个和为(x)的子串,或判不存在。
  • (n,qle10^6)

简单构造题

考虑如果我们有一个和为(x)的子串,则我们必然能通过它得到一个和为(x-2)的子串。

首先如果两端有(2)直接删掉即可,否则两端都是(1)同时删掉即可。

也就是说我们分别找到和为奇数的最大子串及和为偶数的最大子串,然后通过上面的方案就可以构造出所有可能的子串和。

而要找到最大子串,首先整个序列就是对应奇偶性的最大子串,然后分别从两头向内找到第一个(1),比较一下哪边需要删的比较少就选哪边把外头一堆(2)和这个(1)一起删去即可得到改变奇偶性的最大子串。

代码:(O(n))

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000000
using namespace std;
int n,a[N+5],pl[2*N+5],pr[2*N+5];
namespace FastIO
{
	#define FS 100000
	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
	I void read_a() {W(isspace(oc=tc()));for(RI i=1;i<=n;++i) a[i]=oc=='W'?1:2,oc=tc();}
	Tp I void write(Ty x,char y) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc(y);}
	Tp I void writeln(Con Ty& x,Con Ty& y) {write(x,' '),write(y,'
');}
	I void NA() {pc('N'),pc('I'),pc('E'),pc('
');}
}using namespace FastIO;
int main()
{
	RI Qt,i,j,tg=0,s=0;for(read(n,Qt),read_a(),i=1;i<=n;++i) a[i]==1&&(tg=1),s+=a[i];
	RI l[2],r[2],Mx[2];if(l[s&1]=1,r[s&1]=n,Mx[s&1]=s,!tg) Mx[s&1^1]=0;else//整个串是对应奇偶性的最大子串;如果没有1无法改变奇偶性
	{
		for(i=1;a[i]==2;++i);for(j=n;a[j]==2;--j);//分别从左右向内找到第一个1
		RI o=s&1^1;i<=n-j+1?(l[o]=i+1,r[o]=n,Mx[o]=s-(2*i-1)):(l[o]=1,r[o]=j-1,Mx[o]=s-(2*(n-j+1)-1));//选要删数较少的那边删去
	}
	for(i=0;i<=1;++i) W(Mx[i]>0) pl[Mx[i]]=l[i],pr[Mx[i]]=r[i],//记录当前子串和的答案
		a[l[i]]==2?++l[i]:(a[r[i]]==2?--r[i]:(++l[i],--r[i])),Mx[i]-=2;//使得子串和减少2
	RI x;W(Qt--) read(x),pl[x]?writeln(pl[x],pr[x]):NA();return clear(),0;
}
败得义无反顾,弱得一无是处
原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3514.html