一题简单的分块操作,听说要用set卡就打了下但是感觉貌似不用,好像vector处理也能过。
题目链接https://loj.ac/problem/6280
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e5+10; 5 const int inf = 0x3f3f3f3f; 6 int dir[10][10] = {{1,0},{-1,0},{0,1},{0,-1}}; 7 int pos[maxn*2], a[maxn*2], lz[maxn*2], minn[maxn]; 8 int l, r, opt, t, n, c, k; 9 set<int> s[2010]; //用从大到小就是 set<int,greater<int> > s[2010]; 10 11 inline int read() 12 { 13 char ch = getchar(); ll k = 0, f = 1; 14 while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();} 15 while(ch >= '0' && ch <= '9') {k = (k << 1) + (k << 3) + ch - '0'; ch = getchar();} 16 return k * f; 17 } 18 19 inline void reset(int x) 20 { 21 s[x].clear(); 22 s[x].insert(a + (x - 1) * t + 1, a + min(x * t, n) + 1); //更新set 23 } 24 25 inline void inser(int l, int r, int c) 26 { 27 if(pos[l] == pos[r]) 28 { 29 for(int i = l; i <= r; ++i) a[i] += c; 30 reset(pos[l]); 31 } 32 33 else 34 { 35 for(int i = l; i <= pos[l] * t; ++i) a[i] += c; 36 reset(pos[l]); 37 for(int i = (pos[r] - 1) * t + 1; i <= r; ++i) a[i] += c; 38 reset(pos[r]); 39 for(int i = pos[l] + 1; i <= pos[r] - 1; ++i) lz[i] += c; 40 } 41 42 } 43 44 inline int findy(int l, int r, int c) 45 { 46 int ans = -inf; 47 if(pos[l] == pos[r]) 48 { 49 for(int i = l; i <= r; ++i) 50 { 51 if(lz[pos[l]] + a[i] < c && lz[pos[l]] + a[i] > ans) ans = lz[pos[l]] + a[i]; 52 } 53 54 } 55 56 else 57 { 58 for(int i = l; i <= pos[l] * t; ++i) if(lz[pos[l]] + a[i] < c && lz[pos[l]] + a[i] > ans) ans = lz[pos[l]] + a[i]; 59 for(int i = (pos[r] - 1) * t + 1; i <= r; ++i) if(lz[pos[r]] + a[i] < c && lz[pos[r]] + a[i] > ans) ans = lz[pos[r]] + a[i]; 60 for(int i = pos[l] + 1; i <= pos[r] - 1; i++) 61 { 62 int x = c - lz[i]; 63 set<int>::iterator it = s[i].lower_bound(x); 64 if(it == s[i].begin()) continue; //值得注意的是如果用*lower_bound没找到返回的不一定是0,此时就难判断 65 it--; 66 ans = max(ans, *it + lz[i]); 67 } 68 69 } 70 71 return ans; 72 } 73 74 int main() 75 { 76 n = read(); 77 for(int i = 1; i <= n; ++i) a[i] = read(); 78 t = sqrt(n); 79 80 for(int i = 1; i <= n; ++i) 81 { 82 pos[i] = (i - 1)/t + 1; 83 s[pos[i]].insert(a[i]); 84 } 85 86 for(int i = 1; i <= n; ++i) 87 { 88 opt = read(); l = read(); r = read(); c = read(); 89 if(opt == 0) inser(l, r, c); 90 else 91 { 92 k = findy(l, r, c); 93 if(k != -inf) cout<<k<<endl; 94 else cout<<-1<<endl; 95 } 96 97 } 98 99 return 0; 100 }
其中有很多地方代码都可以更加简洁一些,比如维护个L,R数组。但我可能顺着思路写就有点死脑筋,导致检查起来也不太好看。
用*lower_bound()进行判断容易卡(别问我为什么知道。。
第一篇随笔,不周到之处见谅