我们平时建立函数式线段树的顺序都是按照索引建立,值作为线段树的区间,此题我们要按值的顺序建立,将索引作为线段树的区间,又涨姿势了...
具体可以参考爱神的题解: http://blog.csdn.net/acm_cxlove/article/details/8566093
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> #include <bitset> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::stringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; using std::unique; using std::lower_bound; using std::random_shuffle; using std::bitset; using std::upper_bound; using std::multiset; typedef long long LL; typedef unsigned long long ULL; typedef unsigned UN; typedef pair<int, int> PAIR; typedef multimap<int, int> MMAP; typedef LL TY; typedef long double LF; const int MAXN(500010); const int MAXM(50010); const int MAXE(150010); const int MAXK(6); const int HSIZE(13131); const int SIGMA_SIZE(4); const int MAXH(20); const int INFI((INT_MAX-1) >> 1); const ULL BASE(31); const LL LIM(1e13); const int INV(-10000); const int MOD(31313); const double EPS(1e-7); const LF PI(acos(-1.0)); template<typename T> inline void checkmax(T &a, T b){if(b > a) a = b;} template<typename T> inline void checkmin(T &a, T b){if(b < a) a = b;} template<typename T> inline T ABS(const T &a){return a < 0? -a: a;} int ls[MAXN], rs[MAXN], sum[MAXN], lsum[MAXN], rsum[MAXN], root[20010], tab[20010]; int rear; void push_up(int rt) { sum[rt] = sum[ls[rt]]+sum[rs[rt]]; lsum[rt] = max(lsum[ls[rt]], sum[ls[rt]]+lsum[rs[rt]]); rsum[rt] = max(rsum[rs[rt]], sum[rs[rt]]+rsum[ls[rt]]); } void build(int l, int r, int &rt) { rt = rear++; if(l == r) { sum[rt] = lsum[rt] = rsum[rt] = 1; return; } int m = (l+r) >> 1; build(l, m, ls[rt]); build(m+1, r, rs[rt]); push_up(rt); } void updata(int l, int r, int val, int prt, int &rt) { rt = rear++; ls[rt] = ls[prt]; rs[rt] = rs[prt]; if(l == r) { sum[rt] = lsum[rt] = rsum[rt] = -1; return; } int m = (l+r) >> 1; if(val <= m) updata(l, m, val, ls[prt], ls[rt]); else updata(m+1, r, val, rs[prt], rs[rt]); push_up(rt); } int query(int l, int r, int ql, int qr, int rt) { if(ql <= l && qr >= r) return sum[rt]; int m = (l+r) >> 1, ret = 0; if(ql <= m) ret = query(l, m, ql, qr, ls[rt]); if(qr > m) ret += query(m+1, r, ql, qr, rs[rt]); return ret; } int queryl(int l, int r, int ql, int qr, int rt) { if(ql == l && qr == r) return lsum[rt]; int m = (l+r) >> 1, ret; if(qr <= m) ret = queryl(l, m, ql, qr, ls[rt]); else if(ql > m) ret = queryl(m+1, r, ql, qr, rs[rt]); else ret = max(queryl(l, m, ql, m, ls[rt]), query(l, m, ql, m, ls[rt])+queryl(m+1, r, m+1, qr, rs[rt])); return ret; } int queryr(int l, int r, int ql, int qr, int rt) { if(ql == l && qr == r) return rsum[rt]; int m = (l+r) >> 1, ret; if(qr <= m) ret = queryr(l, m, ql, qr, ls[rt]); else if(ql > m) ret = queryr(m+1, r, ql, qr, rs[rt]); else ret = max(queryr(m+1, r, m+1, qr, rs[rt]), query(m+1, r, m+1, qr, rs[rt])+queryr(l, m, ql, m, ls[rt])); return ret; } int n; bool check(int val, int a, int b, int c, int d) { int temp = queryr(0, n-1, a, b, root[val-1]); if(b+1 < c) temp += query(0, n-1, b+1, c-1, root[val-1]); temp += queryl(0, n-1, c, d, root[val-1]); return temp >= 0; } PAIR arr[20010]; int q[4]; int main() { while(~scanf("%d", &n)) { for(int i = 0; i < n; ++i) { scanf("%d", tab+i); arr[i] = PAIR(tab[i], i); } sort(tab, tab+n); int tn = unique(tab, tab+n)-tab; for(int i = 0; i < n; ++i) arr[i].first = lower_bound(tab, tab+tn, arr[i].first)-tab+1; sort(arr, arr+n); rear = 0; build(0, n-1, root[0]); updata(0, n-1, arr[0].second, root[0], root[arr[0].first]); for(int i = 1; i < n; ++i) updata(0, n-1, arr[i].second, root[arr[i-1].first], root[arr[i].first]); int Q, ans = 0; scanf("%d", &Q); while(Q--) { scanf("%d%d%d%d", q, q+1, q+2, q+3); for(int i = 0; i < 4; ++i) q[i] = (q[i]+ans)%n; sort(q, q+4); int l = 1, r = tn+1; while(l < r) { int m = (l+r) >> 1; if(check(m, q[0], q[1], q[2], q[3])) l = m+1; else r = m; } --l; ans = tab[l-1]; printf("%d\n", ans); } } return 0; }