北京集训DAY3

 1 /*
 2     消去合法的序列 剩下的不合法序列一定是 ))....(((...
 3     两种括号个数各加1除2  手算一下即可
 4 */
 5 #include <cctype>
 6 #include <cstdio>
 7 #include <cstring>
 8 
 9 const int MAXN=100010;
10 
11 int len,top,cnt;
12 
13 char s[MAXN];
14 
15 int hh() {
16     freopen("bracket.in","r",stdin);
17     freopen("bracket.out","w",stdout);
18     scanf("%s",s+1);
19     len=strlen(s+1);
20     for(int i=1;i<=len;++i) {
21         if(s[i]=='(') ++top;
22         else if(s[i]==')'&&top) --top;
23         else ++cnt;
24     }
25     int ans=(top+1)/2+(cnt+1)/2;
26     printf("%d\n",ans);
27     fclose(stdin);
28     fclose(stdout);
29     return 0;
30 }
31 
32 int sb=hh();
33 int main(int argc,char**argv) {;}
题解

 1 /*
 2     维护一个f数组 f[i]表示i这个时刻  车上已经坐了几只怪兽了
 3     [X,Y] Z
 4     for (int i=X; i<Y; i++)
 5           MAX=max(MAX,f[i]);
 6     t=min(Z,M-MAX);
 7     for (int i=X; i<Y; i++) f[i]+=t;
 8     ans+=t
 9     cout<<ans;
10     显然 可用线段树维护区间加和区间查询最大值
11 */
12 #include<iostream>
13 #include<cmath>
14 #include<cstdio>
15 #include<cstring>
16 #include<algorithm>
17 #define N 50005
18 #define lson (root<<1)
19 #define rson (root<<1|1)
20 #define Max(a,b) a=a>b?a:b
21 using namespace std;
22 
23 int k,n,m,x,y,ans,tmp,val;
24 
25 int tree[N<<2],mark[N<<2];
26 
27 struct Node{
28     int l,r,peo;
29     bool operator <(const Node &a)const {
30         if(a.r!=r)return r<a.r;
31         return l>a.l;
32     }
33 }node[N];
34 
35 inline int qread() {
36     int x=0,j=1;
37     char ch=getchar();
38     while(ch<'0' || ch>'9'){if(ch=='-')j=-1;ch=getchar();}
39     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
40     return x*j;
41 }
42 void pushdown(int root) {
43     if(!mark[root]) return;
44     int k=mark[root];
45     tree[lson]+=k;tree[rson]+=k;
46     mark[lson]+=k;mark[rson]+=k;
47     mark[root]=0;
48 }
49 int query(int root,int l,int r,int L,int R) {
50     if(l>R||r<L)return 0;
51     if(L<=l&&r<=R)return tree[root];
52     int mid=(l+r)>>1;
53     pushdown(root);
54     int a=query(lson,l,mid,L,R),b=query(rson,mid+1,r,L,R);
55     tree[root]=Max(tree[lson],tree[rson]);
56     return Max(a,b);
57 }
58 void updata(int root,int l,int r,int L,int R,int to) {
59     if(l>R||r<L) return;
60     if(L<=l&&r<=R) {
61         mark[root]+=to;
62         tree[root]+=to;
63         return;
64     }
65     pushdown(root);
66     int mid=(l+r)>>1;
67     updata(lson,l,mid,L,R,to);
68     updata(rson,mid+1,r,L,R,to);
69     tree[root]=Max(tree[lson],tree[rson]);
70 }
71 int main() {
72     freopen("bus.in","r",stdin);
73     freopen("bus.out","w",stdout);
74     k=qread();n=qread();m=qread();
75     for(int i=1;i<=k;i++) {
76         node[i].l=qread();
77         node[i].r=qread();
78         node[i].peo=qread();
79     }
80     sort(node+1,node+k+1);
81     for(int i=1;i<=k;i++) {
82         tmp=query(1,1,n,node[i].l,node[i].r);
83         if(tmp>=m)continue;
84         if(tmp+node[i].peo<=m) val=node[i].peo;
85         else val=m-tmp;
86         ans+=val;
87         updata(1,1,n,node[i].l,node[i].r-1,val);
88     }
89     printf("%d\n",ans);
90     fclose(stdin);fclose(stdout);
91     return 0;
92 }
题解

 1 /*
 2     枚举左上角 n^2  枚举右下角n^2  枚举修改的数  n^2  求和 n^2  ->  n^8
 3     求一个矩阵和,可以通过矩阵前缀和做到O(1)
 4     枚举左上角 n^2  枚举右下角n^2  枚举修改的数  n^2   ->  n^6
 5     预处理出每个矩阵的最小值是多少。   n^4
 6     枚举左上角 n^2  枚举右下角n^2  修改的数已知(修改最小的或者不修改)  -》n^4 
 7     n,m<=300  
 8     假如我们不要求修改数,查询最大子矩阵  
 9     有n个数,查询最大子段和  O(n)
10     for (i=1; i<=n; i++) f[i]=max(f[i-1]+a[i],a[i]);
11     max{f[i]} = 最大子段和
12     要求我们修改数
13     修改的数一定是最小的那个数。
14     f[i][0]以i结尾并且没有数被修改过的最大和
15     f[i][1]以i结尾并且有数被修改过的最大和  //a[i]  第i列的和
16     for (int i=1; i<=n; i++)
17     {    
18           f[i][0]=max(f[i-1][0]+a[i],a[i]);
19       f[i][1]=max(f[i-1][1]+a[i],f[i-1][0]+a[i]-MIN[i]+P,a[i]-MIN[i]+P);
20     }
21     max{f[?][0/1]} 是答案
22 */
23 #include <cmath>
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cassert>
27 #include <algorithm>
28 
29 const int INF=1000000000;
30 const int MAXN=305;
31 
32 int n,m,ans,P,k;
33 
34 int a[MAXN][MAXN],MIN[MAXN],b[MAXN],dp[MAXN][2],s[MAXN][MAXN];
35 
36 inline int min(int a,int b) {
37     return a>b?b:a;
38 }
39 
40 inline int max(int a,int b) {
41     return a>b?a:b;
42 }
43 
44 int hh() {
45     freopen("puzzle.in","r",stdin);
46     freopen("puzzle.out","w",stdout);
47     while(scanf("%d",&n)) {
48         ans=-INF;
49         scanf("%d%d",&m,&P); assert(1<=n&&n<=300&&1<=m&&m<=300&&-1000<=P&&P<=1000);
50         for(int i=1;i<=n;i++)
51           for(int j=1;j<=m;j++) {scanf("%d",&a[i][j]); assert(-1000<=a[i][j]&&a[i][j]<=1000); }
52         for(int i=1;i<=n;i++)
53           for(int j=1;j<=m;j++)
54             s[i][j]=s[i-1][j]+a[i][j];
55         for(int i=1;i<=n;i++) {
56             for(int j=1;j<=m;j++) MIN[j]=a[i][j];
57             for(int j=i;j<=n;j++) {
58                 for(int k=1;k<=m;k++) MIN[k]=min(MIN[k],a[j][k]);
59                 for(int k=1;k<=m;k++) b[k]=s[j][k]-s[i-1][k];
60                 dp[0][1]=-INF;
61                 for(int k=1;k<=m;k++) dp[k][0]=max(dp[k-1][0]+b[k],b[k]),dp[k][1]=max(max(dp[k-1][1]+b[k],dp[k-1][0]+b[k]-MIN[k]+P),b[k]-MIN[k]+P);
62                 for(int k=1;k<m;k++) ans=max(ans,max(dp[k][0],dp[k][1]));
63                 if(i==1&&j==n) {
64                     ans=max(ans,dp[m][1]);
65                     int sum=0;
66                     for(int k=m; k>1; k--) {sum+=b[k]; ans=max(ans,sum);}
67                 } else
68                   ans=max(ans,max(dp[m][1],dp[m][0]));
69             }
70         }
71         printf("%d\n",ans);
72     }
73     return 0;
74 }
75 
76 int sb=hh();
77 int main(int argc,char**argv) {;}
题解

 

posted @ 2017-10-10 09:56  拿叉插猹哈  阅读(126)  评论(0编辑  收藏  举报