zoukankan      html  css  js  c++  java
  • 【洛谷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;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    使用 ASP.NET Core MVC 创建 Web API(五)
    使用 ASP.NET Core MVC 创建 Web API(四)
    使用 ASP.NET Core MVC 创建 Web API(三)
    使用 ASP.NET Core MVC 创建 Web API(二)
    使用 ASP.NET Core MVC 创建 Web API(一)
    学习ASP.NET Core Razor 编程系列十九——分页
    学习ASP.NET Core Razor 编程系列十八——并发解决方案
    一个屌丝程序猿的人生(九十八)
    一个屌丝程序猿的人生(九十七)
    一个屌丝程序猿的人生(九十五)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3514.html
Copyright © 2011-2022 走看看