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;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    Phone List(字典树)
    Dating with girls(1)(二分+map+set)
    Color the ball(树状数组+线段树+二分)
    python模块导入总结
    Python爬虫之定时抢购淘宝商品
    Celery多队列配置
    python垃圾回收机制
    python变量、对象和引用你真的明白了吗
    使用 supervisor 管理 Celery 服务
    Supervisor的作用与配置
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3514.html
Copyright © 2011-2022 走看看