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