A
模拟,判断y>=x且y<=x+n-m是否成立。
#include<bits/stdc++.h> using namespace std; #define maxx 3000 int n,a,b,c,s,m,t,x,y; map<int,int> M; pair<int,int> all[maxx]; int ans=0; int anss=0; int main() { cin>>t; for(int i=1;i<=t;++i) {cin>>n>>m>>x>>y; if(y>=x&&y<=x+n-m) cout<<"Yes\n"; else cout<<"No\n"; } }B
设一个合法解为a,b,则gcd(a,b)=x,lcm(a,b)=y,而gcd(a,b)*lcm(a,b)=x*y=a*b。
则a与b是xy的约数,枚举所有约数后判断是否gcd(a,b)=x,从小到大枚举。
#include<bits/stdc++.h> using namespace std; #define maxx 3000 #define int long long int n,a,b,c,s,m,t,x,y; pair<int,int> all[maxx]; int ans=0; int anss=0; signed main() { cin>>t; for(int i=1;i<=t;++i) {cin>>x>>y; int z=x*y; for(int i=1;i<=sqrt(z);++i) { if(z%i!=0) continue; if(__gcd(i,z/i)==x) { cout<<i<<" "<<z/i<<"\n"; goto h; } } cout<<-1<<"\n"; h:; } }C
贪心
题目可以转换为bi∈[ai-k,ai+k],且bi非减。
为了减少前数字对后面的影响,每个点尽量向右取和向左取且保证合法,分别判断。
#include<bits/stdc++.h> using namespace std; #define maxx 1200000 int n,a,b,c,s,m,t,x,y,k; int all[maxx]; int ans=0; int anss=0; int main() { cin>>t; for(int i=1;i<=t;++i) {cin>>n>>k; for(int i=1;i<=n;++i) cin>>all[i]; int x=all[1]-k; int wr=0; for(int i=2;i<=n;++i) { if(all[i]+k<x) { ++wr; break; } else if(all[i]-k<=x&&all[i]+k>=x) ; else x=all[i]-k; } x=all[1]+k; for(int i=2;i<=n;++i) { if(all[i]+k<x) { ++wr; break; } else x=all[i]+k; } if(wr==2) cout<<"No\n"; else cout<<"Yes\n"; } }D
注意题意:1.是翻转不是反转,2.每次处理独立,而不是逐步修改。
如果1,2均满足后者,需要使用线段树来进行处理,大约如下代码,没做验证。
#include<bits/stdc++.h> using namespace std; #define INF 1e18 #define maxx 5080000 #define maxx2 0x3f3f3f3f int a,b,d,k,m,t,n,ansmax,Smax,x,ans1,ans2,neww,c; int l,r,q; string s; int xmax,ymax; int pj; int sum=0; int all[maxx]; struct point { int sum0,sum1;//连续的个数 int ld,rd; int leng; int tag; }JD[maxx]; int ls(int root) { return 2*root; } int rs(int root) { return 2*root+1; } void update_from_son(int root,int l,int r) { int mid=(l+r)/2; JD[root].ld=JD[ls(root)].ld; JD[root].rd=JD[rs(root)].rd; JD[root].sum0=JD[ls(root)].sum0+JD[rs(root)].sum0; JD[root].sum1=JD[ls(root)].sum1+JD[rs(root)].sum1; JD[root].leng=JD[ls(root)].leng; if(JD[ls(root)].rd==JD[rs(root)].ld&&JD[ls(root)].rd==0) --JD[root].sum0; if(JD[ls(root)].rd==JD[rs(root)].ld&&JD[ls(root)].rd==1) --JD[root].sum1; if(JD[ls(root)].leng==mid-l+1&&JD[ls(root)].rd==JD[rs(root)].ld) JD[root].leng=JD[root].leng+JD[rs(root)].leng; } void push_down(int root) { if(JD[root].tag==0) return ; JD[ls(root)].tag=(JD[ls(root)].tag+1)%2; JD[rs(root)].tag=(JD[rs(root)].tag+1)%2; JD[ls(root)].ld=(JD[ls(root)].ld+1)%2; JD[ls(root)].rd=(JD[ls(root)].rd+1)%2; swap(JD[ls(root)].sum0,JD[ls(root)].sum1); JD[rs(root)].ld=(JD[rs(root)].ld+1)%2; JD[rs(root)].rd=(JD[rs(root)].rd+1)%2; swap(JD[rs(root)].sum0,JD[rs(root)].sum1); } void build(int root,int l,int r) { if(l==r) { if(all[l]==1) JD[root].sum1=1; else JD[root].sum0=1; JD[root].ld=all[l]; JD[root].rd=all[l]; JD[root].leng=1; return; } int mid=(l+r)/2; build(ls(root),l,mid); build(rs(root),mid+1,r); update_from_son(root,l,r); } void modify(int root,int l,int r,int ql,int qr) { if(l==ql&&r==qr) { JD[root].ld=(JD[root].ld+1)%2; JD[root].rd=(JD[root].rd+1)%2; swap(JD[root].sum0,JD[root].sum1); JD[root].tag=(JD[root].tag+1)%2; return ; } int mid=(l+r)/2; push_down(root); if(ql<=mid) modify(ls(root),l,mid,ql,min(qr,mid)); if(qr>=mid+1) modify(rs(root),mid+1,r,max(mid+1,ql),qr); update_from_son(root,l,r); } int query(int root,int l,int r) { return JD[1].sum1; } signed main() { cin>>n>>q>>s; for(int i=0;i<n;++i) all[i+1]=s[i]-'0'; build(1,1,n); for(int i=1;i<=q;++i) { cin>>l>>r; modify(1,1,n,l,r); cout<<query(1,1,n)<<"\n"; } }
正解为如下
首先处理出所有连续1段的长度,然后翻转在左右端点不一致的时候会影响端点的数值,在端点分类讨论即可。
#include<bits/stdc++.h> using namespace std; #define INF 1e18 #define maxx 88 #define maxx2 0x3f3f3f3f int a,b,d,k,m,t,n,ansmax,Smax,x,ans1,ans2,neww,c; int q; string s; int l,r; int xmax,ymax; int pj; int sum=0; int all[maxx]; int ans; signed main() { cin>>n>>q>>s; for(int i=0;i<n;++i) all[i+1]=s[i]-'0'; int x=1; for(int i=1;i<=n;) { x=i; while(++i<=n) { if(all[i]!=all[x]) { if(all[x]==1) ++ans; x=i; break; } } } if(all[n]==1) ++ans; all[0]=all[n+1]=-1; for(int i=1;i<=q;++i) { cin>>l>>r; int qq=ans; if(all[l]==0&&all[r]==1&&all[l-1]!=1) ++qq; if(all[l]==0&&all[r]==1&&all[r+1]!=1) --qq; if(all[l]==1&&all[r]==0&&all[l-1]!=1) --qq; if(all[l]==1&&all[r]==0&&all[r+1]!=1) ++qq; cout<<qq<<"\n"; } }