很远古的一道题,当时打的跟(*机房和谐*)一样,后来用$ O(q*n) $的算法卡到了T75
1 #include<iostream>
2 #include<cstdio>
3 #include<cstdlib>
4 #include<cmath>
5 #include<cstring>
6 #define ll long long
7 #define m(a) memset(a,0,sizeof(a))
8 using namespace std;
9 const int maxn=1e5+100;
10 int ans,x,y,w,n,m,a[maxn],l,r,z;
11 int main()
12 {
13 scanf("%d%d",&n,&m);
14 for(register int i=1;i<=n;i++) scanf("%d",&a[i]);
15 for(register int i=1;i<=m;++i)
16 {
17 scanf("%d%d",&x,&y);
18 l=r=w=0;
19 ans=-1e5;
20 z=x;
21 for(register int j=x;j<=y;++j)
22 {
23 w+=a[j];
24 if(w>ans)
25 {
26 ans=w;
27 l=z;
28 r=j;
29 }
30 if(w<0)
31 {
32 z=j+1;
33 w=0;
34 }
35 }
36 printf("%d %d %d\n",l,r,ans);
37 }
38 return 0;
39 }
现在打起来这个题是真的简单(虽然我早在4月份已经颓了题解)
首先维护4个w,3个x,3个y,分别代表:
(尖括号代表从哪里转移过来)
(0):左段最大值以及其左右端点
1>w[ls][0]
2>w[ls][3]+w[rs][0]
(1):中间最大值以及其左右端点
1>w[ls][1]
2>w[rs][1]
3>w[ls][2]+w[rs][0]
(2):右段最大值以及其左右端点
1>w[rs][2]
2>w[rs][3]+w[ls][2]
(3):整段的最大值。
1>w[ls][3]+w[rs][3]
因为要输出最小字典序,所以某些最大值相等的情况要考虑字典序的问题
否则会WA88(可能WA0?)
1 #include<bits/stdc++.h>
2 using namespace std;
3 const int N=1e5+10;
4 int n,m,f[N];
5 struct Tree{int l,r,x[3],y[3],w[4];}a[N*4];
6 int read()
7 {
8 int sum,k=1;char s;
9 while(s=getchar(),s<'0'||s>'9')if(s=='-')k=-1;sum=s-'0';
10 while(s=getchar(),s>='0'&&s<='9') sum=sum*10+s-'0';
11 return k*sum;
12 }
13 void merge(int k,Tree ls,Tree rs)
14 {
15 if(ls.w[0]>=ls.w[3]+rs.w[0])
16 {
17 a[k].w[0]=ls.w[0];
18 a[k].x[0]=ls.x[0];
19 a[k].y[0]=ls.y[0];
20 }
21 else
22 {
23 a[k].w[0]=ls.w[3]+rs.w[0];
24 a[k].x[0]=ls.x[0];
25 a[k].y[0]=rs.y[0];
26 }
27 if(ls.w[2]+rs.w[0]>ls.w[1]||(ls.w[2]+rs.w[0]==ls.w[1]&&ls.x[2]<ls.x[1]))
28 {
29 if(ls.w[2]+rs.w[0]>=rs.w[1])
30 {
31 a[k].w[1]=ls.w[2]+rs.w[0];
32 a[k].x[1]=ls.x[2];
33 a[k].y[1]=rs.y[0];
34 }
35 else
36 {
37 a[k].w[1]=rs.w[1];
38 a[k].x[1]=rs.x[1];
39 a[k].y[1]=rs.y[1];
40 }
41 }
42 else
43 {
44 if(ls.w[1]>=rs.w[1])
45 {
46 a[k].w[1]=ls.w[1];
47 a[k].x[1]=ls.x[1];
48 a[k].y[1]=ls.y[1];
49 }
50 else
51 {
52 a[k].w[1]=rs.w[1];
53 a[k].x[1]=rs.x[1];
54 a[k].y[1]=rs.y[1];
55 }
56 }
57 if(ls.w[2]+rs.w[3]>=rs.w[2])
58 {
59 a[k].w[2]=ls.w[2]+rs.w[3];
60 a[k].x[2]=ls.x[2];
61 a[k].y[2]=rs.y[3];
62 }
63 else
64 {
65 a[k].w[2]=rs.w[2];
66 a[k].x[2]=rs.x[2];
67 a[k].y[2]=rs.y[2];
68 }
69 a[k].w[3]=ls.w[3]+rs.w[3];
70 }
71 void build(int k,int l,int r)
72 {
73 a[k].l=l;a[k].r=r;
74 if(l==r)
75 {
76 a[k].x[0]=a[k].x[1]=a[k].x[2]=l;
77 a[k].y[0]=a[k].y[1]=a[k].y[2]=l;
78 a[k].w[0]=a[k].w[1]=a[k].w[2]=a[k].w[3]=f[l];
79 return;
80 }
81 int mid=(l+r)>>1;
82 build(k<<1,l,mid);
83 build(k<<1|1,mid+1,r);
84 merge(k,a[k<<1],a[k<<1|1]);
85 }
86 Tree query(int k,int l,int r)
87 {
88 if(a[k].l>=l&&a[k].r<=r) return a[k];
89 int mid=(a[k].l+a[k].r)>>1;
90 Tree X,Y;
91 if(l<=mid) X=query(k<<1,l,r);
92 if(r>mid) Y=query(k<<1|1,l,r);
93 if(l<=mid&&r>mid)
94 {
95 merge(0,X,Y);
96 return a[0];
97 }
98 else if(l<=mid) return X;
99 else return Y;
100 }
101 signed main()
102 {
103 //freopen("1.in","r",stdin);
104 //freopen("1.out","w",stdout);
105 n=read();m=read();
106 for(int i=1;i<=n;i++) f[i]=read();
107 build(1,1,n);
108 for(int i=1,x,y,ans,l,r;i<=m;i++)
109 {
110 x=read();y=read();
111 Tree S=query(1,x,y);
112 ans=max(S.w[0],max(S.w[1],S.w[2]));
113 if(S.w[0]>=S.w[1])
114 {
115 if(S.w[0]>=S.w[2]) l=S.x[0],r=S.y[0];
116 else l=S.x[2],r=S.y[2];
117 }
118 else
119 {
120 if(S.w[1]>=S.w[2]) l=S.x[1],r=S.y[1];
121 else l=S.x[2],r=S.y[2];
122 }
123 printf("%d %d %d\n",l,r,ans);
124 }
125 return 0;
126 }