【题解】洛谷P3514、P6859 :LIZ-Lollipop、蝴蝶与花
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; }
P6859 蝴蝶与花
这次加上了修改操作怎么办呢,没事用树状数组维护前缀和即可,但是时间还是不太够,我们通过发现问题本质。
我们想二分查找该怎么做,枚举左端点二分查找右端点,当 \([l,r_1]\) 区间和 \(k\) 为只能为 \(s\) 或 \(s+1\),如果 \(k\) 大于 \(s+1\) 时,\(r\) 右移一格一定不小于 \(s\)。
如果 \([l+1,r_2]\) 的区间和也是 \(s+1\) 的话那必然 \(a_l\) 和 \(a_{r_1}\) 为 2,这个可以反证法,继续向下类举下去如果两个端点一直是 \(2\) 的话区间和就不会变。
所以我们 \(1\) 作为左端点二分右端点 \(pos\),统计点 \(1\) 后的 \(2\) 的数量和 \(pos\) 后的 \(2\) 的数量,向后平移即可。
树状数组 \(O(n\log^2 n)\)。
#include <bits/stdc++.h> #define int long long #define ls p<<1 #define rs p<<1|1 #define re register #define ll long long #define lb(x) x&-x const int N=4e6+100; const int mod=998244353; using namespace std; int n,m; int a[N]; int sum[N*2]; void addsum(int x,int k){ while(x<=n){ sum[x]+=k; x+=lb(x); } } int querysum(int x){ int ans=0; while(x){ ans+=sum[x]; x-=lb(x); } return ans; } signed main(){ // freopen("kingdom3.in","r",stdin); // freopen("a.out","w",stdout); ios::sync_with_stdio(false); cin.tie(nullptr); cin>>n>>m; for(re int i=1;i<=n;i++){ cin>>a[i]; addsum(i,a[i]); } while(m--){ int x,y; char c; cin>>c; if(c=='A'){ cin>>x; if(x==0){ cout<<"none\n"; continue; } int l=1,r=n,mid,pos; while(l<=r){ mid=(l+r)>>1; if(querysum(mid)>=x){ pos=mid; r=mid-1; } else{ l=mid+1; } } int z=querysum(pos); if(z<x){ cout<<"none\n"; continue; } if(z==x){ cout<<1<<" "<<pos<<"\n"; continue; } int len1=0,len2=0; l=1,r=n; while(l<=r){ mid=(l+r)>>1; if(querysum(mid)==mid*2){ len1=mid; l=mid+1; } else{ r=mid-1; } } l=1,r=n; while(l<=r){ mid=(l+r)>>1; if(querysum(pos+mid-1)-querysum(pos-1)==mid*2){ len2=mid; l=mid+1; } else{ r=mid-1; } } if(len1<len2){ if(querysum(pos+len1)-querysum(2+len1-1)!=x){ cout<<"none\n"; continue; } cout<<2+len1<<" "<<pos+len1; } else{ if(querysum(pos+len2)-querysum(len2)!=x){ cout<<"none\n"; continue; } cout<<1+len2<<" "<<pos+len2; } cout<<"\n"; } else{ cin>>x>>y; addsum(x,-a[x]); addsum(x,y); a[x]=y; } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」