P3514 [POI2011] LIZ-Lollipop
很好的思维题,也是一个结论题,只有1、2的性质很重要,结论:当存在 \(k(k>2)\),必然可以得到 \(k-2\)。
得到 \(k\) 的区间 \(l_k\) 和 \(r_k\) 必然会有 \(a_{l_k}=2\) 或 \(a_{r_k}=2\) 或 \(a_{l_k}=a_{r_k}=1\),这样无论如何都能减去一段或两端得到 \(k-2\)。
这样如果一个数存在,那比他小的所有奇偶性相同的数就都存在,我们就可以求出最大的奇数偶数来判断是否合法。
求答案区间,我们可以在求最大奇偶数时记录存在该数的区间,然后通过逆推式求出每个存在的数的区间。
#include <bits/stdc++.h>
#define int long long
#define re register
const int N=2e6+10;
using namespace std;int n,m,a[N],sum[N],mx[4];
int l[N];
int r[N];void up(int k,int x,int y){if(k>mx[k%2]){mx[k%2]=k;l[k]=x;r[k]=y;}
}void down(int &l,int &r,int pl,int pr){if(pl==0&&pr==0){return;}l=pl;r=pr;if(a[pl]==2){l++;}else if(a[pr]==2){r--;}else{l++;r--;}
}signed main(){ios::sync_with_stdio(false);cin.tie(nullptr);cin>>n>>m;for(int i=1;i<=n;i++){char c;cin>>c;a[i]=(c=='T')?2:1;sum[i]=sum[i-1]+a[i];}for(int i=1;i<=n;i++){up(sum[i]-sum[0],1,i);up(sum[n]-sum[i],i+1,n);}up(sum[n]-sum[0],1,n);for(int i=2*n;i>=1;i--){down(l[i],r[i],l[i+2],r[i+2]);}for(int i=1;i<=m;i++){int k;cin>>k;if(k>mx[k%2]){cout<<"NIE\n";continue;}cout<<l[k]<<" "<<r[k]<<"\n";}return 0;
}