X day3

题目

官方题解

T1:

一道水题

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<stack>
using namespace std;
inline int read(){
    int f=1,ans=0;char c;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
char str,str1[100011];
stack<int> sta;
int ans;
int main(){
     scanf("%s",str1+1);
     int len=strlen(str1+1);
     for(int i=1;i<=len;i++){
         if(str1[i]=='('){
             sta.push(1);
         }else{
             if(sta.empty()) ans++,sta.push(1);
             else sta.pop();
         }
     }
     cout<<ans+sta.size()/2;
}
View Code

T2:

线段树优化贪心,我们可以先将他们的末尾排序,然后依次看一看是否能放

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define int long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
int n,m,k;
struct node{
    int u,v,w;
}x[500001];
int sum;
int maxn[200004],ans[200004];
void pushdown(int k,int l,int r){
    int mid=l+r>>1;
    if(ans[k]!=0){
        ans[k<<1]+=ans[k];
        ans[k<<1|1]+=ans[k];
        maxn[k<<1]+=ans[k];
        maxn[k<<1|1]+=ans[k];
        ans[k]=0;
    }return;
}
int query(int k,int l,int r,int x,int y){
    if(x<=l&&r<=y) return maxn[k];
    int  mid=l+r>>1,mmaxn=0;
    pushdown(k,l,r);
    if(x<=mid) mmaxn=max(mmaxn,query(k<<1,l,mid,x,y));
    if(mid<y) mmaxn=max(mmaxn,query(k<<1|1,mid+1,r,x,y));
    maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
    return mmaxn;
}
void update(int k,int l,int r,int x,int y,int w){
    if(x<=l&&r<=y){ans[k]+=w;maxn[k]+=w;return;}
    pushdown(k,l,r);
    int mid=l+r>>1;
    if(x<=mid) update(k<<1,l,mid,x,y,w);
    if(mid<y) update(k<<1|1,mid+1,r,x,y,w);
    maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
    return;
}
bool cmp(node x1,node x2){return x1.v<x2.v;}
signed main(){
    m=read(),n=read(),k=read();
    for(int i=1;i<=m;i++) x[i].u=read(),x[i].v=read(),x[i].w=read();
    sort(x+1,x+m+1,cmp);
    for(int i=1;i<=m;i++){
        int res=query(1,1,n,x[i].u,x[i].v),ans=0;
        if(res>=k) continue;
        if(res+x[i].w<=k) ans=x[i].w;
        else ans=k-res;
        update(1,1,n,x[i].u,x[i].v-1,ans);
        sum+=ans;
    }
    cout<<sum;
    return 0;
    
}
View Code

 T3:

我们容易想到一维情况是最大子序列,然后二位也是如此。每次确定$[l,r]$表示当前子矩阵在$l-r$行的最大值,然后二维的像一维那样搞。但是这种可以删除一个数,所以我们需要在定一维表示是否删除一个数

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read(){
    int f=1,ans=0;char c;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
int n,m,k,dp[301][2],a[301][301],minv[301],s[301][301],sum[301],maxn;
int main(){
    n=read(),m=read(),k=read();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++) a[i][j]=read(),s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
    }/*l i R j*/
    for(int i=1;i<=n;i++){//L
        memset(minv,127/3,sizeof(minv));
        for(int j=i;j<=n;j++){//R
            memset(dp,0,sizeof(dp));
            sum[0]=0;
            for(int kk=1;kk<=m;kk++){//INIT
                minv[kk]=min(minv[kk],a[j][kk]);
                sum[kk]=s[j][kk]-s[i-1][kk]-s[j][kk-1]+s[i-1][kk-1];
            }
            for(int kk=1;kk<=m;kk++){
                dp[kk][0]=max(dp[kk-1][0]+sum[kk],sum[kk]);
                dp[kk][1]=max(dp[kk-1][1]+sum[kk],max(dp[kk-1][0]+sum[kk]-minv[kk]+k,sum[kk]-minv[kk]+k));
                maxn=max(maxn,max(dp[kk][0],dp[kk][1]));
            }
        }
    }
    cout<<maxn;
}
View Code
原文地址:https://www.cnblogs.com/si-rui-yang/p/9914667.html