【BZOJ4491】我也不知道題目名字是什麽 [線段樹]
阿新 • • 發佈:2017-05-20
lose 接下來 數量 uil data mat content -- sof
Submit: 315 Solved: 173
[Submit][Status][Discuss]
1 2 3 4 5 6 5 4 3
5
1 6
1 7
2 7
1 9
5 9
6
5
6
4
4491: 我也不知道題目名字是什麽
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 315 Solved: 173
[Submit][Status][Discuss]
Description
給定一個序列A[i],每次詢問l,r,求[l,r]內最長子串,使得該子串為不上升子串或不下降子串
Input
第一行n,表示A數組有多少元素
接下來一行為n個整數A[i]
接下來一個整數Q,表示詢問數量
接下來Q行,每行2個整數l,r
Output
對於每個詢問,求[l,r]內最長子串,使得該子串為不上升子串或不下降子串
Sample Input
91 2 3 4 5 6 5 4 3
5
1 6
1 7
2 7
1 9
5 9
Sample Output
66
5
6
4
HINT
N,Q<=50000
Solution
直接上線段樹,記錄一下一個區間內:左邊最長,右邊最長,整體最優。再分一下不下降和不上升即可。
Code
1 #include<iostream>
2 #include<string>
3 #include<algorithm>
4 #include<cstdio>
5 #include<cstring>
6 #include<cstdlib>
7 #include<cmath>
8 #include<queue>
9 using namespace std;
10
11 const int ONE = 500005;
12 const int INF = 2147483640;
13
14 int n,Q;
15 int x,y;
16 int a[ONE];
17
18 struct power
19 {
20 int len;
21 int Lval, Rval;
22 int Lup,Ldn, Rup,Rdn;
23 int Maxup, Maxdn;
24
25 friend power operator +(power a, power b)
26 {
27 power A;
28 A.len = a.len + b.len;
29 A.Lval = a.Lval; A.Rval = b.Rval;
30
31 A.Lup = a.Lup; if(a.Lup == a.len && a.Rval <= b.Lval) A.Lup += b.Lup;
32 A.Ldn = a.Ldn; if(a.Ldn == a.len && a.Rval >= b.Lval) A.Ldn += b.Ldn;
33
34 A.Rup = b.Rup; if(b.Rup == b.len && a.Rval <= b.Lval) A.Rup += a.Rup;
35 A.Rdn = b.Rdn; if(b.Rdn == b.len && a.Rval >= b.Lval) A.Rdn += a.Rdn;
36
37 A.Maxup = max(a.Maxup, b.Maxup);
38 A.Maxdn = max(a.Maxdn, b.Maxdn);
39
40 if(a.Rval <= b.Lval) A.Maxup = max(A.Maxup, a.Rup+b.Lup);
41 if(a.Rval >= b.Lval) A.Maxdn = max(A.Maxdn, a.Rdn+b.Ldn);
42
43 return A;
44 }
45 }Node[ONE];
46
47 int get()
48 {
49 int res=1,Q=1;char c;
50 while( (c=getchar())<48 || c>57 )
51 if(c==‘-‘)Q=-1;
52 res=c-48;
53 while( (c=getchar())>=48 && c<=57 )
54 res=res*10+c-48;
55 return res*Q;
56 }
57
58 void Build(int i,int l,int r)
59 {
60 if(l == r)
61 {
62 Node[i].Lval = Node[i].Rval = a[l];
63 Node[i].len = 1;
64 Node[i].Lup = Node[i].Rup = Node[i].Ldn = Node[i].Rdn = 1;
65 Node[i].Maxup = Node[i].Maxdn = 1;
66 return;
67 }
68
69 int mid = l+r>>1;
70 Build(i<<1, l,mid); Build(i<<1|1, mid+1,r);
71 Node[i] = Node[i<<1] + Node[i<<1|1];
72 }
73
74 power Query(int i,int l,int r,int L,int R)
75 {
76 if(L==l && r==R) return Node[i];
77 int mid = l+r>>1;
78 if(mid+1 > R) return Query(i<<1, l,mid,L,R);
79 else if(L > mid) return Query(i<<1|1, mid+1,r,L,R);
80 else return Query(i<<1, l,mid,L,mid) + Query(i<<1|1, mid+1,r,mid+1,R);
81 }
82
83 int main()
84 {
85 n = get();
86 for(int i=1; i<=n; i++) a[i] = get();
87 Build(1,1,n);
88
89 Q = get();
90 while(Q--)
91 {
92 x = get(); y = get();
93 power res = Query(1,1,n,x,y);
94 printf("%d\n", max(res.Maxup, res.Maxdn) );
95 }
96 }
View Code
【BZOJ4491】我也不知道題目名字是什麽 [線段樹]