Codeforces Round #546题解
A题
遍历找到第一个不覆盖它的答案
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e5+10; struct node{ int l,r; }s[N]; int main(){ ios::sync_with_stdio(false); int n,k; cin>>n; int i; for(i=1;i<=n;i++) cin>>s[i].l>>s[i].r; cin>>k; k--; for(i=1;i<=n;i++){ if(s[i].l<=k&&s[i].r>k||s[i].l>k){ cout<<n-i+1<<endl; break; } } return 0; }
B题
贪心题,刚开始的要特殊讨论,之后的就是不断往后放就行,这样就不用多搬石头
走的方向需要考虑一下,往短的那边走
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e5+10; struct node{ int l,r; }s[N]; int main(){ ios::sync_with_stdio(false); int n,k; cin>>n; int i; for(i=1;i<=n;i++) cin>>s[i].l>>s[i].r; cin>>k; k--; for(i=1;i<=n;i++){ if(s[i].l<=k&&s[i].r>k||s[i].l>k){ cout<<n-i+1<<endl; break; } } return 0; }
C题
规律题,不难看出,每条副对角线的元素要相等才行,因为只会在副对角线变化并且这条线上的答案可以通过2*2的方阵随意排列
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e5+10; int a[1010][1010]; int b[1010][1010]; vector<int> num1[N],num2[N]; int main(){ ios::sync_with_stdio(false); int n,m; cin>>n>>m; int i,j; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ cin>>a[i][j]; num1[i+j].push_back(a[i][j]); } } for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ cin>>b[i][j]; num2[i+j].push_back(b[i][j]); } } for(i=1;i<=n+m;i++){ sort(num1[i].begin(),num1[i].end()); sort(num2[i].begin(),num2[i].end()); for(int j=0;j<(int)num1[i].size();j++){ if(num1[i][j]!=num2[i][j]){ cout<<"NO"<<endl; return 0; } } } cout<<"YES"<<endl; return 0; }
D题
这题确实没想到,老贪心败狗了,我们发现当最后一个数要往前移,那么他必须要和前面那个能够调换,我们观察一个性质,当一个位置上的数能够和他后面的数调换位置直到碰到最后一个数,那么就能答案++
并且这个不会改变后面数的顺序,因此倒序枚举,维护栈,栈中存的是不能再调换的数。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=5e5+10; vector<int> num[N]; int ins[N]; int a[N]; int main(){ ios::sync_with_stdio(false); int n,m; cin>>n>>m; int i; for(i=1;i<=n;i++) cin>>a[i]; for(i=1;i<=m;i++){ int a1,b; cin>>a1>>b; num[a1].push_back(b); } ins[a[n]]=1; int cnt; int ans=0; for(i=n-1;i>=1;i--){ cnt=0; for(auto x:num[a[i]]){ if(ins[x]) cnt++; } if(n-i-ans==cnt){ ans++; } else{ ins[a[i]]=1; } } cout<<ans<<endl; return 0; }
E题
这题带给了我一些启发。
刚开始做的时候总是想着怎么维护这个k,也考虑过将a和k合并成一个值维护,但是想不出什么好方法
后来看了题解发现,这个其实可以通过前缀和维护,因为主要是考虑如何做这个连续的更新,我们发现如果将k的前缀和si与a组成关系,难度将大大减小
原来的ai+ki>ai+1其实就是现在的ai-ki-1-ki-2...>ai+1-ki-k-1...,如果处理不了,那么消灭它
因此用bi替代这个式子发现我们是在维护一个具有单调性的式子,那么只要二分找到最右边的位置,将区间覆盖成bi+x就行,这一点是根据题目,一位位递推过去。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e5+10; const ll inf=-1e18; int a[N],b[N]; int vis[N]; ll pre[N],sum[N]; struct node{ int l,r; ll sum; ll lazy; ll mi; }tr[N<<2]; void pushup(int u){ tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum; tr[u].mi=min(tr[u<<1].mi,tr[u<<1|1].mi); } void build(int u,int l,int r){ if(l==r){ tr[u]={l,r,a[l]-sum[l],inf,a[l]-sum[l]}; } else{ tr[u]={l,r}; tr[u].lazy=inf; int mid=l+r>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); pushup(u); } } void pushdown(int u){ ll x=tr[u].lazy; tr[u<<1].lazy=x; tr[u<<1|1].lazy=x; tr[u<<1].sum=(tr[u<<1].r-tr[u<<1].l+1)*x; tr[u<<1|1].sum=(tr[u<<1|1].r-tr[u<<1|1].l+1)*x; tr[u<<1].mi=tr[u<<1|1].mi=x; tr[u].lazy=-1e18; } void modify(int u,int l,int r,ll x){ if(tr[u].l>=l&&tr[u].r<=r){ tr[u].sum=(tr[u].r-tr[u].l+1)*x; tr[u].lazy=x; tr[u].mi=x; return ; } if(tr[u].lazy!=-1e18) pushdown(u); int mid=tr[u].l+tr[u].r>>1; if(l<=mid) modify(u<<1,l,r,x); if(r>mid) modify(u<<1|1,l,r,x); pushup(u); } ll query(int u,int l,int r){ if(tr[u].l>=l&&tr[u].r<=r){ return tr[u].sum; } if(tr[u].lazy!=-1e18) pushdown(u); int mid=tr[u].l+tr[u].r>>1; ll ans=0; if(l<=mid) ans+=query(u<<1,l,r); if(r>mid) ans+=query(u<<1|1,l,r); return ans; } int find(int u,int l,int r,ll x){ if(tr[u].l==tr[u].r){ return tr[u].l; } if(tr[u].lazy!=-1e18) pushdown(u); int mid=tr[u].l+tr[u].r>>1; if(tr[u<<1|1].mi<=x) return find(u<<1|1,l,r,x); else{ return find(u<<1,l,r,x); } } int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; for(i=1;i<=n;i++){ cin>>a[i]; } for(i=2;i<=n;i++){ cin>>b[i]; sum[i]=sum[i-1]+b[i]; } for(i=2;i<=n;i++){ pre[i]=pre[i-1]+sum[i]; } int q; cin>>q; build(1,1,n); while(q--){ string s; cin>>s; if(s=="+"){ int l,x; cin>>l>>x; ll tmp=query(1,l,l); int r=find(1,l,n,tmp+x); modify(1,l,r,tmp+x); } else{ int l,r; cin>>l>>r; cout<<query(1,l,r)+pre[r]-pre[l-1]<<endl; } } return 0; }
没有人不辛苦,只有人不喊疼