链接: http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1524
Description
给包含n个数的初始序列,A[1], A[2], ..., A[n]。
给q多个操作,操作如下:
1 a b v, 把[a, b] 的值改为v,即A[a] = A[a+1] = ... = A[b] = v。
2 a b, 查询[a, b] 之间的相同数的连续和最大值。
在[a, b]区间内,相同数的连续和最大值就是Sum(A[i], A[i+1], A[j]), a <= i <= j <= b,并且A[i] = A[i+1] = A[i+2] = A[i+3] = ... = A[j]。
Input
有多组测试数据,不超过5组测试数据。
对于每组测试数据,第一个为 n (n<=10^5),第二行为n个数,每个数的范围[0, 1000]。
第三行为 q (q<=10^5),表示查询的次数。
接下来有q个操作,格式如下:
1 a b v, 把[a, b] 的值改为v,即A[a] = A[a+1] = ... = A[b] = v。
2 a b, 查询[a, b] 之间的相同数的连续和最大值。
其中 1 <= a <= b <=n,0 <= v <= 1000.
Output
每组测试数据先输出一行"Case id:",id从1开始计数。
对于每个查询,输出一行,包含一个整数,为相同数的连续和最大值。
Sample Input
5
2 2 1 2 3
3
2 1 4
1 1 3 2
2 1 5
7
120 985 727 979 68 558 732
4
1 2 5 627
2 2 7
2 4 5
1 5 7 571
Sample Output
Case 1:
4
8
Case 2:
2508
1254
代码如下: (这代码当时把我弄疯了)
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #define maxn 100005 #define clr(x)memset(x,0,sizeof(x)) using namespace std; int max(int a,int b) { return a>b?a:b;} int min(int a,int b) { return a<b?a:b;} int lva[maxn<<4]; // 最左面的值 int lnu[maxn<<4]; // 最左面的数的个数 int rva[maxn<<4]; // 最右面的值 int rnu[maxn<<4]; // 最右面的数的个数 int mva[maxn<<4]; // 区间最大连续值 int add[maxn<<4]; // 延迟标记 int v[maxn], re[100005]; void creat(int l,int r,int rt) { add[rt] = -1; if(l == r) { lva[rt] = rva[rt]=v[l]; lnu[rt] = rnu[rt]=1; mva[rt] = v[l]; return; } int m = (l+r) >> 1; creat(l, m, rt<<1); creat(m+1, r, rt<<1|1); lva[rt] = lva[rt<<1]; lnu[rt] = lnu[rt<<1]; rva[rt] = rva[rt<<1|1]; rnu[rt] = rnu[rt<<1|1]; if(lva[rt<<1] == lva[rt<<1|1] && lnu[rt<<1] == (m-l+1)) lnu[rt] += lnu[rt<<1|1]; if(rva[rt<<1] == rva[rt<<1|1] && rnu[rt<<1|1] == r-m) rnu[rt] += rnu[rt<<1]; mva[rt] = max(mva[rt<<1], mva[rt<<1|1]); if(rva[rt<<1] == lva[rt<<1|1]) { mva[rt] = max(mva[rt], rva[rt<<1]*rnu[rt<<1]+lva[rt<<1|1]*lnu[rt<<1|1]); } } void update(int L, int R, int c, int l, int r, int rt) { if(L <= l && r <= R) { add[rt] = c; lva[rt] = rva[rt] = c; lnu[rt] = rnu[rt] = r-l+1; mva[rt] = c*(r-l+1); return; } int m = (l+r) >> 1; if(add[rt] != -1) { add[rt<<1] = add[rt<<1|1] = add[rt]; lva[rt<<1] = rva[rt<<1] = lva[rt<<1|1] = rva[rt<<1|1] = add[rt]; lnu[rt<<1] = rnu[rt<<1] = m-l+1; lnu[rt<<1|1] = rnu[rt<<1|1] = r - m; mva[rt<<1] = (m-l+1) * add[rt]; mva[rt<<1|1] = (r-m) * add[rt]; add[rt] = -1; } if(L <= m) update(L, R, c, l, m, rt<<1); if(R > m) update(L, R, c, m+1, r, rt<<1|1); lva[rt] = lva[rt<<1]; lnu[rt] = lnu[rt<<1]; rva[rt] = rva[rt<<1|1]; rnu[rt] = rnu[rt<<1|1]; if(lva[rt<<1] == lva[rt<<1|1] && lnu[rt<<1] == (m-l+1)) lnu[rt] += lnu[rt<<1|1]; if(rva[rt<<1] == rva[rt<<1|1]&& rnu[rt<<1|1] == r-m) rnu[rt] += rnu[rt<<1]; mva[rt]=max(mva[rt<<1],mva[rt<<1|1]); if(rva[rt<<1] == lva[rt<<1|1]) { mva[rt] = max(mva[rt], rva[rt<<1]*rnu[rt<<1]+lva[rt<<1|1]*lnu[rt<<1|1]); } } int query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) return mva[rt]; int m = (l+r) >> 1; if(add[rt] != -1) { add[rt<<1] = add[rt<<1|1] = add[rt]; lva[rt<<1] = rva[rt<<1] = lva[rt<<1|1] = rva[rt<<1|1] = add[rt]; lnu[rt<<1] = rnu[rt<<1] = m-l+1; lnu[rt<<1|1] = rnu[rt<<1|1] = r - m; mva[rt<<1] = (m-l+1) * add[rt]; mva[rt<<1|1] = (r-m) * add[rt]; add[rt] = -1; } if(R <= m) return query(L, R, l, m, rt<<1); else if(L > m) return query(L, R, m+1, r, rt<<1|1); else { int res = 0; if(rva[rt<<1] == lva[rt<<1|1]) res = (min(rnu[rt<<1], m-L+1) + min(lnu[rt<<1|1], R-m)) * rva[rt<<1]; return max(res, max(query(L, m, l, m, rt<<1), query(m+1, R, m+1, r, rt<<1|1))); } } int n, a, b, c, m, op, cas = 1, top = 0, tot; void Init() { for(int i=1; i<=n; i++) scanf("%d",&v[i]); creat(1, n, 1); scanf("%d", &m); tot = 0; } int main() { while(~scanf("%d", &n)) { Init(); printf("Case %d:\n", cas++); while(m--) { scanf("%d", &op); if(op == 1) { scanf("%d %d %d", &a, &b, &c); update(a, b, c, 1, n, 1); }else { scanf("%d %d", &a, &b); printf("%d\n", query(a, b, 1, n, 1)); } } } return 0; }
HLG 1524 最大 (离散化线段树)