HDU 3333 & 主席树
题意:
balabala
SOL:
这题用主席树怎么做呢...貌似一模一样...一个一个建n棵的线段树.先把上一棵树复制下来,当a[i]出现过,就把这棵树里的那个位置去掉------一模一样的思维...就是用空间换时间达到在线罢了...然而他的在线比我的离线还快是什么鬼...线段树果然比树状数组慢不止一点点啊...
CODE:
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <set> #include <unordered_map> #include <queue> #include <stack> #include <vector> #include <string> #include <algorithm> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 30000+10, MAXM = MAXN*50; int lc[MAXM],rc[MAXM],tol; LL sum[MAXM]; int a[MAXN], rt[MAXN]; unordered_map<int,int> vis; void update(int &u, int x, int y, int p, LL v) { sum[tol] = sum[u]+v,lc[tol] = lc[u],rc[tol] = rc[u]; u = tol++; if(x == y) return; int m = (x+y)>>1; if(p <= m) update(lc[u],x,m,p,v); else update(rc[u],m+1,y,p,v); } LL query(int u, int x, int y, int ql, int qr) { if(ql <= x && y <= qr) return sum[u]; int m = (x+y)>>1; LL ans = 0; if(ql <= m) ans += query(lc[u],x,m,ql,qr); if(qr > m) ans += query(rc[u],m+1,y,ql,qr); return ans; } int main() { int t; scanf("%d%*c", &t); while(t--) { int n; scanf("%d", &n); repe(i,1,n) scanf("%d", &a[i]); tol = 1; vis.clear(); repe(i,1,n) { rt[i] = rt[i-1]; if(vis.find(a[i]) != vis.end()) { int tmp = rt[i-1]; update(tmp,1,n,vis[a[i]],-a[i]); rt[i] = tmp; update(rt[i],1,n,i,a[i]); } else { rt[i] = rt[i-1]; update(rt[i],1,n,i,a[i]); } vis[a[i]] = i; } int q; scanf("%d", &q); rep(i,0,q) { int x,y; scanf("%d %d", &x, &y); printf("%I64d\n", query(rt[y],1,n,x,y)); } } return 0; }
Sometimes it s the very people who no one imagines anything of. who do the things that no one can imagine.