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;
}
View Code

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;
}
View Code

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;
}
View Code

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;
}
View Code

 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;
}
View Code

 

posted @ 2020-12-23 21:04  朝暮不思  阅读(98)  评论(0编辑  收藏  举报