Helter Skelter (扫描线 + 离散化 + 树状数组)
扫描线:按照其中一个区间的标记为pos,然后左区间标记d为正影响,有区间标记d为负影响,然后根据所有的pos排序。pos从小扫到大,那么对于某一个区间一定会被扫过2次,那么经过2次之后就只剩下中间那一段的影响了,但是先提前扫过去的话后面的区间就会影响到前面的区间,反过来却不会。所以求答案的时候也是按照查询区间的左部那么我只需要一边录入数据,一边求就可以了。
然后对于1的区间只需要用一个线段树/树状数组就可以将判断是否符合了,还有就是树状数组离散化之后对速度有些许帮助。
#include<bits/stdc++.h> using namespace std; const int maxm = 1e6 + 7; int in[maxm], discre[maxm << 1], tr[maxm << 1]; int l, r, L, R, opL, disL; char ans[maxm]; void TreeAdd(int rt, int num){ while(rt <= disL){ tr[rt] += num; rt = rt + (rt & -rt); } } int TreeSum(int rt){ int ret = 0; while(rt){ ret += tr[rt]; rt = rt - (rt & -rt); } return ret; } struct OP{ int pos, d, L, R; bool operator < (const OP& a)const{ return pos < a.pos; } }op[maxm << 1]; struct QUERY{ int a, b, id; bool operator < (const QUERY& A)const{ return a < A.a; } }query[maxm]; void join(){ op[opL].d = 1;op[opL].pos = l; op[opL].L = L;op[opL ++].R = R; op[opL].d = -1;op[opL].pos = r + 1; op[opL].L = L;op[opL ++].R = R; discre[disL ++] = L; discre[disL ++] = R; } int main(){ int T, n, m, k;scanf("%d", &T); while(T --){ k = disL = opL = 0; scanf("%d%d",&n, &m); for(int i = 1; i <= n; i ++) scanf("%d",&in[i]); for(int i = 0; i < m; i ++){ scanf("%d%d",&query[i].a, &query[i].b), query[i].id = i; discre[disL ++] = query[i].b; } sort(query, query + m); for(int i = 1; i <= n; i ++){ ///单区间 if(i & 1){l = 0, r = in[i], L = R = 0; join();} else {l = r = 0, L = 0, R = in[i]; join();} ///双区间 if(i & 1 && i < n){l = L = 0; r = in[i]; R = in[i + 1]; join();} else if(i < n) {l = L = 0; r = in[i + 1]; R = in[i]; join();} ///多区间 l = r = L = R = 0; for(int j = i + 1; j < n; j ++){ l += ((j & 1) ? in[j] : 0); L += ((j & 1) ? 0 : in[j]); r = l + ((i & 1) ? in[i] : 0) + ((j & 1) ? 0 : in[j + 1]); R = L + ((i & 1) ? 0 : in[i]) + ((j & 1) ? in[j + 1] : 0); join(); } } sort(op, op + opL); sort(discre, discre + disL); disL = unique(discre, discre + disL) - discre; for(int i = 0; i <= disL; i ++) tr[i] = 0; for(int i = 0; i < m; i ++){ for(;k < opL && query[i].a >= op[k].pos; k ++){ int ll = lower_bound(discre, discre + disL, op[k].L) - discre + 1; int rr = lower_bound(discre, discre + disL, op[k].R) - discre + 1; TreeAdd(ll, op[k].d); TreeAdd(rr + 1, -1 * op[k].d); } int qq = lower_bound(discre, discre + disL, query[i].b) - discre + 1; ans[query[i].id] = '0' + (TreeSum(qq) > 0); } ans[m] = 0; printf("%s\n",ans); } return 0; }
more crazy more get!