我们平时建立函数式线段树的顺序都是按照索引建立,值作为线段树的区间,此题我们要按值的顺序建立,将索引作为线段树的区间,又涨姿势了...
具体可以参考爱神的题解: 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;
}