cf round546 cde

第一题会卡一下同时用set和cin。。

其他的注意下矩阵对角线下标的应用即可

#include<bits/stdc++.h>
using namespace std;
#define maxn 2005
int mp1[maxn][maxn],n,m,mp2[maxn][maxn];
vector<int>s1[maxn],s2[maxn];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&mp1[i][j]),s1[i+j].push_back(mp1[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&mp2[i][j]),s2[i+j].push_back(mp2[i][j]);
    
    for(int i=2;i<=n+m;i++){
        sort(s1[i].begin(),s1[i].end());
        sort(s2[i].begin(),s2[i].end());
        if(s1[i]!=s2[i]){
            puts("NO");
            return 0;
        }
    }
    puts("YES");
} 
/*
问题可转化为有多少个点可以把最后一个点(n)推移上来
按位置将所有点排序,建立一个集合s
起初将最后一个点放在集合里,然后倒序访问之前的结点,
如果结点i可以将n推上来,那么之后的结点j再要将n推上来时就不用考虑i,
否则需要考虑j是否可以推到i后面,再然后将n推上来 
    如果之前结点i有边到达集合里的所有点,那么这个结点就可以把点n推上来,
    如果不行,这个点i放入集合中
复杂度分析:每条边都会在集合里判断一次,mlogn 
*/
#include<bits/stdc++.h>
#include<set>
using namespace std;
#define maxn 500005
int m,n,pos[maxn],id[maxn];
set<int>s,G[maxn];
set<int>::iterator it;
 
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        scanf("%d",&id[i]),pos[id[i]]=i;
    int u,v;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        G[u].insert(v);
    }
    
    int ans=0;
    s.insert(id[n]);
    for(int i=n-1;i>=1;i--){
        int cur=id[i],flag=0;
        for(it=s.begin();it!=s.end();it++)
            if(G[cur].find(*it)==G[cur].end()){
                flag=1;
                s.insert(cur);
                break;
            }
        if(!flag)ans++;
    }
    cout<<ans<<endl;
}

e也太难了。。留个坑吧

补坑。。区间覆盖线段树调了半天,最后发现有个地方没写long long ...气死我了.

所以总结一下,,区间覆盖和区间更新的pushdown还是有点差距的,,还有本题的lazy初始值要设为INF

/*
给定数组a1...an, k1...kn-1
两种操作:
第一种为ai+x,完成本次操作后若ai+1<ai+ki,则ai+1=ai+ki,以此类推
    即后面的数不得小于前面的数+ki
第二种为求和操作 
推导公式可得a1<=a2-sumk1<=a3-sumk2<=a4-sumk3...<=an-sumkn-1
令 bi=ai-sumki-1
b1<=b2<=b3<=b4...<=bn
ai+x <=> bi+x,同时所有在bi后面且小于bi+x的数都要变成bi+x
    所以直接用lower_bound找到第一个不小于bi+x的数 
用线段树维护bi,进行区间覆盖操作
query时先query 区间bi的和,再使用前缀和求出区间sumki的值
注意lazy 
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
#define ll long long
ll n,m,a[maxn],k[maxn],b[maxn],sumk[maxn],sumkk[maxn];
#define INF 1e18 
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
ll sum[maxn<<2],lazy[maxn<<2];
inline void pushup(int rt){
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
inline void pushdown(int l,int r,int rt){
    if(lazy[rt]!=INF+1){
        int m=l+r>>1;
        sum[rt<<1]=lazy[rt]*(m-l+1);
        sum[rt<<1|1]=lazy[rt]*(r-m);
        lazy[rt<<1]=lazy[rt];
        lazy[rt<<1|1]=lazy[rt];
        lazy[rt]=INF+1;
    }
}
void build(int l,int r,int rt){
    lazy[rt]=INF+1;
    if(l==r){sum[rt]=b[l];return;}
    int m=l+r>>1;
    build(lson);build(rson);
    pushup(rt);
}
void modify(int L,int R,ll val,int l,int r,int rt){
    if(L<=l&&R>=r){
        lazy[rt]=val;sum[rt]=val*(r-l+1);
        return;
    }
    pushdown(l,r,rt);
    int m=l+r>>1;
    if(L<=m)modify(L,R,val,lson);
    if(R>m)modify(L,R,val,rson);
    pushup(rt);
}

ll query(int L,int R,int l,int r,int rt){
    if(L<=l && R>=r)return sum[rt];
    pushdown(l,r,rt);
    int m=l+r>>1;
    ll res=0;
    if(L<=m)res+=query(L,R,lson);
    if(R>m)res+=query(L,R,rson);
    return res;
} 
void add(int i,ll val){
    if(val==0)return;
    ll cur=query(i,i,1,n,1)+val;//查询第l个点当前值 
    int l=i,r=n,mid,ans=l;//查询最右边的比cur小的数 
    while(l<=r){
        mid=l+r>>1;
        if(query(mid,mid,1,n,1)<cur)
            ans=mid,l=mid+1;
        else r=mid-1;
    }
    modify(i,ans,cur,1,n,1);
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<n;i++)cin>>k[i];
    for(int i=2;i<=n;i++)sumk[i]=sumk[i-1]+k[i-1];
    for(int i=1;i<=n;i++)b[i]=a[i]-sumk[i];
    for(int i=2;i<=n;i++)sumkk[i]=sumkk[i-1]+sumk[i];
    build(1,n,1);
    cin>>m;
    while(m--){
        char op[2];ll l,r;
        cin>>op>>l>>r;
        if(op[0]=='+')add(l,r);
        else cout<<query(l,r,1,n,1)+sumkk[r]-sumkk[l-1]<<"
";
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zsben991126/p/10519971.html