acm数据结构整理
2015-03-12 14:32
183 查看
一、区间划分 //区间划分+持久化并查集:区间连通情况统计。 inline bool comp(Ask x, Ask y){return x.km == y.km ? x.l > y.l : x.km > y.km ; } inline void init()//把编号相同的放一起,l从大到小;{ int i ; ms = sqrt(1.0*n) ; //大小 mg = n/ms ; //块数 mg = mg*ms == n ? mg : mg + 1 ; for(i = 1 ; i <= n ; i ++) e[i].clear() ; } /*********************持久化并查集**********************************/ void solve()//区间划分{ int i = 1, j, k, l, r ; sort(ask+1, ask+1+q, comp) ; while(i <= q) //询问 { k = ask[i].km ; for(; i <= q && ask[i].km == k && ask[i].l > (k-1)*ms ; i ++) //处理区间小于ms的询问 ans[ask[i].no] = bfAnswer(i) ; if(i > q || ask[i].km != k ) //全部为小区间 continue ; r = (k-1)*ms ; //最右端 initSet(lp, 1, r) ; //初始化并查集 ; for(j = 1 ; j <= r ; j ++) vis[j] = 0 ; while(i <= q && ask[i].km == k ) //求解第k块的所有大询问; { l = ask[i].l ; for(j = r ; j >= l ; j -- ) //加入顶点j addVex(lp, j, (k-1)*ms) ; r = j ; for(; i <= q && ask[i].km == k && ask[i].l == l ; i ++) //计算所有左端等于l的区间; { ans[ask[i].no] = unionRSet(ask[i].no, l, (k-1)*ms+1, ask[i].r ) ; //右端暴力合并 ; } } } } 二、2B树:动态区间比x小的数的个数。 void DT_insert(int rt, int x, int s ){ int i = DN, j, p ; getBinary(x) ; j = dig[i--] ; if(root[rt].next[j] == -1) { root[rt].next[j] = ++ tot ; pool[tot].set() ; } if(!j) root[rt].sum += s ; p = root[rt].next[j] ; while(i) { j = dig[i--] ; if(pool[p].next[j] == -1) { pool[p].next[j] = ++ tot ; pool[tot].set() ; } if(!j)pool[p].sum += s ; p = pool[p].next[j] ; } } int DT_count(int rt, int x){ int i = DN, j, p, ans = 0 ; getBinary(x) ; j = dig[i--] ; if(j) ans += root[rt].sum ; if(root[rt].next[j] == -1) return ans ; p = root[rt].next[j] ; while(i) { j = dig[i--] ; if(j) ans += pool[p].sum ; if(pool[p].next[j] == -1) return ans ; p = pool[p].next[j] ; } return ans ; } void DT_build(){ int i, k ; size = sqrt(double(n)) ; mg = n/size ; mg = mg*size == n ? mg : mg+1 ; for(i = 1 ; i <= mg ; i ++) root[i].set() ; for(i = 1 ; i <= n ; i ++) { k = (i-1)/size + 1 ; DT_insert(k, ar[i], 1) ; } bs = 10*size ; bmg = n/bs ; bmg = bmg*bs == n ? bmg : bmg + 1 ; for(i = 1 ; i <= bmg+1 ; i ++) root[MAXS+i].set() ; for(i = 1 ; i <= n ; i ++) { k = (i-1)/bs + 1 ; DT_insert(MAXS+k, ar[i], 1) ; } } int DT_query(int l, int r, int x){ int i, k, ans = 0, bk ; k = (l-1)/size + 1 ; k = size*(k-1)+1 == l ? k : k + 1 ; //前 for(i = l ; i <= r && i < (k-1)*size+1 ; i ++) ans = ar[i] < x ? ans+1 : ans ; for(; i <= r && r-i+1 >= size && (k%10 != 1) ; i += size, k ++) //小块 ans += DT_count(k, x) ; for(bk = (k-1)/10+1 ; i <= r && r-i+1 >= bs ; i += bs, bk ++, k += 10) ans += DT_count(MAXS+bk, x) ;//大块 for(; i <= r && r-i+1 >= size ; i += size, k ++) //小块 ans += DT_count(k, x) ; for(; i <= r ; i ++) ans = ar[i] < x ? ans+1 : ans ; return ans ; } 三、树链剖分 1. 树上区间[u, v] 异或 x 的最大值 // 持久化2B树 + 树链剖分(区间可直接合并) inline void insert(int rt, int x) ; //建一颗空树 inline void addNumber(int pre, int &rt, int id, int x){//持久化 int i = SD, p ; bool j ; rt = ++dcnt ; p = rt ; while(i >= 0 ) { pool[p] = pool[pre] ; j = x&(1<<i) ; pool[p].mx[j] = id ; pool[p].next[j] = ++dcnt ; p = dcnt ; pre = pool[pre].next[j] ; i -- ; } pool[p].x = x ; } inline int DTcount(int rt,int l,int x)//计算前缀树[1,r]中下标>=l的与x的最大异或值 /*******c******************树链剖分*************************/ void DFS(int u){ int i, to ; siz[u] = 1 ; son[u] = 0 ; for(i = head[u] ; i != -1 ; i = e[i].next ) { to = e[i].to ; if(to != fa[u]) { fa[to] = u ; dep[to] = dep[u] + 1 ; DFS(to) ; if(siz[son[u]] < siz[to]) son[u] = to ; siz[u] += siz[to] ; } } } void cutLink(int u, int tp){ w[u] = ++cnt ; top[u] = tp ; if(son[u]) cutLink(son[u], tp) ; for(int i = head[u] ; i != -1 ; i = e[i].next) { int to = e[i].to ; if(to != fa[u] && to != son[u]) cutLink(to, to) ; } } void buildTree(){ dep[1] = 1 ; cnt = fa[1] = siz[0] = 0 ; DFS(1) ; cutLink(1, 1) ; int i ; for(i = 1 ; i <= n ; i ++) val[w[i]] = ar[i] ; pool[0].set() ; dcnt = T[0] = 0 ; for(i = 1 ; i <= cnt ; i ++) insert(T[0], val[i]) ; for(i = 1 ; i <= cnt ; i ++) addNumber(T[i-1], T[i], i, val[i]) ;//持久化思 } int getAns(int u, int v, int x){ int ans = 0, tu = top[u], tv = top[v], tmp ; if(u == v) return DTcount(T[w[u]], w[v], x) ; ; while(tu != tv) //如果不在同一条链上 { if(dep[tu] < dep[tv]) {swap(tu, tv) ; swap(u, v) ; } tmp = DTcount(T[w[u]], w[tu], x ) ; //查询从u到tu的父亲的最大值 ans = max(ans, tmp) ; u = fa[tu] ; tu = top[u] ; } if(dep[u] < dep[v]) swap(u, v) ; tmp = DTcount(T[w[u]], w[v], x) ; return max(ans, tmp) ; } 2. BFS实现建树 int leaf[MAXN], ns[MAXN], ct[MAXN]; void BFS(int rt){ int i, h = 0, t = 0, l = 0, r = 0 ; int u, to ; que[t++] = rt ; for(i = 1 ; i <= n ; i ++) { siz[i] = 1 ; ct[i] = ns[i] = son[i] = 0 ; } while (h < t) // calculate the dep. { u = que[h++] ; for(i = head[u] ; i != -1 ; i = e[i].next) { to = e[i].to ; if(to != fa[u]) { ns[u] ++ ; fa[to] = u ; dep[to] = dep[u] + 1 ; que[t++] = to ; } } } for(i = 1 ; i <= n ; i ++) if(ns[i] == 0) leaf[r++] = i ; while(l < r) { to = leaf[l++] ; u = fa[to] ; siz[u] += siz[to] ; ct[u] ++ ; if(ct[u] == ns[u] && u ) leaf[r++] = u ; } h = t = 0 ; que[t++] = rt ; siz[0] = 0 ; while (h < t) { u = que[h++] ; for(i = head[u] ; i != -1 ; i = e[i].next) { to = e[i].to ; if(to != fa[u]) { if(siz[son[u]] < siz[to]) son[u] = to ; que[t++] = to ; } } } } void BFS_cutLink(int rt, int tp){ int i, u, to, h = 0, t = 0 ; que[t++] = rt ; while (h < t) { u = que[h++] ; w[u] = ++cnt ; top[u] = u ; to = son[u] ; while (to) { w[to] = ++cnt ; top[to] = u ; for(i = head[to] ; i != -1 ; i = e[i].next) if(e[i].to != fa[to] && e[i].to != son[to]) que[t ++] = e[i].to ; to = son[to] ; } for(i = head[u] ; i != -1 ; i = e[i].next) { to = e[i].to ; if(to != fa[u] && to != son[u]) que[t++] = to ; } } } 3. 非直接合并查询:树上最长上升子序列 /*********************线段树成段更新最长上升子序列*************************/ void Up(int step){ L[step].lx = L[lson].lx + ( (L[lson].lx==L[lson].len && val[L[rson].left] > val[L[lson].right])?L[rson].lx:0) ; L[step].rx = L[rson].rx + ((L[rson].rx==L[rson].len &&val[L[rson].left] > val[L[lson].right])?L[lson].rx:0) ; L[step].mx = max(max(L[lson].mx,L[rson].mx),val[L[rson].left] > val[L[lson].right]?(L[lson].rx+L[rson].lx):0); L[step].dlx = L[lson].dlx + ( (L[lson].dlx == L[lson].len && val[L[rson].left] < val[L[lson].right]) ? L[rson].dlx : 0 ); L[step].drx = L[rson].drx + ((L[rson].drx == L[rson].len && val[L[rson].left] < val[L[lson].right]) ? L[lson].drx : 0 ) ; L[step].dmx = max(max(L[lson].dmx,L[rson].dmx),val[L[rson].left] < val[L[lson].right] ? (L[lson].drx+L[rson].dlx) : 0 ) ; } void build(int step,int l,int r){ L[step].left=l; L[step].right=r; L[step].len = r-l+1 ; L[step].mid=(l+r)/2; if(l==r) { L[step].lx = L[step].rx = L[step].mx = 1 ; L[step].dlx =L[step].drx = L[step].dmx = 1 ; return ; } …… ; } inline void unionNode(int l, int r, int ar ){ L[ar].lx = L[l].lx + ((L[l].lx==L[l].len && val[L[r].left] > val[L[l].right]) ? L[r].lx : 0) ; L[ar].rx = L[r].rx + ((L[r].rx==L[r].len && val[L[r].left] > val[L[l].right]) ? L[l].rx : 0) ; L[ar].mx = max(max(L[l].mx,L[r].mx),val[L[r].left] > val[L[l].right]?(L[l].rx+L[r].lx):0); L[ar].dlx = L[l].dlx + ((L[l].dlx == L[l].len && val[L[r].left] < val[L[l].right]) ? L[r].dlx : 0 ); L[ar].drx = L[r].drx + ((L[r].drx == L[r].len && val[L[r].left] < val[L[l].right]) ? L[l].drx : 0 ) ; L[ar].dmx = max(max(L[l].dmx,L[r].dmx),val[L[r].left] < val[L[l].right] ? (L[l].drx+L[r].dlx) : 0 ) ; L[ar].left = L[l].left ; L[ar].right = L[r].right ; L[ar].len = L[l].len + L[r].len ; } int query(int step,int l,int r){ if(l==L[step].left&&r==L[step].right) return step ; …… ; else { int lt = query(lson,l,L[step].mid); int rt = query(rson,L[step].mid+1,r); ++scnt ; unionNode(lt, rt, scnt) ; return scnt ; } } /*************************树链剖分*************************/ inline int unionAns(int l, int r){ int tmp = max(L[l].dmx, L[r].mx), ans ; if(val[L[l].left] < val[L[r].left]) ans = L[r].lx + L[l].dlx ; else ans = 0 ; ans = max(tmp, ans) ; return ans ; } int getAns(int u, int v){ if(u == v) return L[query(1, w[u], w[u])].mx ; int tu = top[u], tv = top[v] ; int ar, tr, ur, vr ; scnt = 4*cnt +1; ar = ++scnt ; ur = -1 ; vr = -1 ; while (tu != tv) { if(dep[tu] > dep[tv])//calculate the link tu -> u. { tr = query(1, w[tu], w[u]) ; if(ur == -1) ur = tr ; else { ++scnt ; unionNode(tr, ur, scnt); //tr is left node. ur = scnt ; } u = fa[tu] ; tu = top[u] ; } else { tr = query(1, w[tv], w[v]) ; if(vr == -1) vr = tr ; else { ++scnt ; unionNode(tr, vr, scnt) ; // tr is left node. vr = scnt ; } v = fa[tv] ; tv = top[v] ; } } if(dep[u] >= dep[v])// v is root. { tr = query(1, w[v], w[u]) ; if(ur == -1) ur = tr ; else { scnt ++ ; unionNode(tr, ur, scnt) ; ur = scnt ; } u = v ; } else { tr = query(1, w[u], w[v]) ; if(vr == -1) vr = tr ; else { ++scnt ; unionNode(tr, vr, scnt) ; vr = scnt ; } v = u ; } if(ur == -1) return L[vr].mx ; else if(vr == -1) return L[ur].dmx ; return unionAns(ur, vr) ; // calculate the answer of u->v } 4. 树上最大字段和 /*********************线段树最大子段和*************************/ inline void Up(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1] ; lx[rt] = max(lx[rt<<1|1], lx[rt<<1] + sum[rt<<1|1]) ; rx[rt] = max(rx[rt<<1], rx[rt<<1|1] + sum[rt<<1]) ; mx[rt] = max(mx[rt<<1], mx[rt<<1|1]) ;//不合并 mx[rt] = max(mx[rt], lx[rt<<1] + rx[rt<<1|1]) ; //合并 } inline void Down(int rt, int L, int R){ if(d[rt] != INF) { int x = d[rt] ; int mid = (L+R) >> 1 ; d[rt] = INF ; d[rt<<1] = d[rt<<1|1] = x ; sum[rt<<1] = (LL)x*(mid-L+1) ; sum[rt<<1|1] = (LL)x*(R-mid) ; lx[rt<<1] = rx[rt<<1] = mx[rt<<1] = x > 0 ? sum[rt<<1] : 0 ; lx[rt<<1|1] = rx[rt<<1|1] = mx[rt<<1|1] = x > 0 ? sum[rt<<1|1] : 0 ; } } inline void unionNode(int l, int r, int ar ){ sum[ar] = sum[l] + sum[r] ; lx[ar] = max(lx[r], lx[l]+sum[r]) ; rx[ar] = max(rx[l], rx[r]+sum[l]) ; mx[ar] = max(mx[l], mx[r]) ; mx[ar] = max(mx[ar], lx[l]+rx[r]) ; } void build(int rt, int l, int r){ d[rt] = INF ; if(l == r) { sum[rt] = lx[rt] = rx[rt] = mx[rt] = val[l] ; return ; } …… ; } void updata(int rt, int L, int R, int l, int r, int x){ if(L == l && r == R) { sum[rt] = (R-L+1)*x ; lx[rt] = rx[rt] = mx[rt] = x > 0 ? sum[rt] : 0 ; d[rt] = x ; return ; } Down(rt, L, R) ; …… ; } int query(int rt, int L, int R, int l, int r){ if(L == l && R == r) return rt ; Down(rt, L, R) ; …… ; else { int x = query(rt<<1, L, mid, l, mid) ; int y = query(rt<<1|1, mid+1, R, mid+1, r) ; ++scnt ; unionNode(x, y, scnt) ; return scnt ; } } /*************************树链剖分*************************/ inline void unionAns(int x, int y, int ar){ mx[ar] = max(mx[x], mx[y]) ; mx[ar] = max(mx[ar], rx[x]+rx[y]) ; } int getAns(int u, int v){ if(u == v) return query(1, 1, cnt, w[u], w[u]) ; int tu = top[u], tv = top[v] ; int ar, tr, ur, vr ; scnt = 4*cnt +1; ar = ++scnt ; ur = -1 ; vr = -1 ; while (tu != tv) { if(dep[tu] > dep[tv])//calculate the link tu -> u. { tr = query(1, 1, cnt, w[tu], w[u]) ; if(ur == -1) ur = tr ; else { ++scnt ; unionNode(tr, ur, scnt); //tr is left node. ur = scnt ; } u = fa[tu] ; tu = top[u] ; } else { tr = query(1, 1, cnt, w[tv], w[v]) ; if(vr == -1) vr = tr ; else { ++scnt ; unionNode(tr, vr, scnt) ; // tr is left node. vr = scnt ; } v = fa[tv] ; tv = top[v] ; } } if(dep[u] >= dep[v]) { tr = query(1, 1, cnt, w[v], w[u]) ; if(ur == -1) ur = tr ; else { scnt ++ ; unionNode(tr, ur, scnt) ; ur = scnt ; } u = v ; } else { tr = query(1, 1, cnt, w[u], w[v]) ; if(vr == -1) vr = tr ; else { ++scnt ; unionNode(tr, vr, scnt) ; vr = scnt ; } v = u ; } if(ur == -1) return vr ; else if(vr == -1) return ur ; unionAns(ur, vr, ar) ; // calculate the answer of u->v return ar ; } 四、持久化线段树 /*******************静态 Kth number ***************************************/ void build(int &rt, int l, int r ){ rt = ++tot ; sum[rt] = 0 ; if(l >= r) return ; …… ; } void updata(int &rt, int pre, int l, int r, int i, int v){ rt = ++tot ; ls[rt] = ls[pre] ; rs[rt] = rs[pre] ; sum[rt] = sum[pre] + v ; if(l >= r ) return ; int mid = l+r >> 1 ; if(mid >= i ) updata(ls[rt], ls[pre], l, mid, i, v) ; else updata(rs[rt], rs[pre], mid+1, r, i, v) ; } int query(int R, int L, int l, int r, int k){ if(l >= r) return l ; int t = sum[ls[R]] - sum[ls[L]] ; int mid = l+r >> 1 ; if(t >= k) return query(ls[R], ls[L], l, mid, k) ; else return query(rs[R], rs[L], mid+1, r, k-t) ; } /***************************************************************/ void solve(){ sort(ord+1, ord+1+n, comp) ; cnt = rk[ord[1]] = 1 ; nar[cnt] = ar[ord[1]] ; for(i = 2 ; i <= n ; i ++) { if(ar[ord[i]] != ar[ord[i-1]]) { rk[ord[i]] = ++cnt ; nar[cnt] = ar[ord[i]] ; } else rk[ord[i]] = cnt ; } tot = 0 ; build(T[0], 1, cnt) ; for(i = 1 ; i <= n ; i ++) updata(T[i], T[i-1], 1, cnt, rk[i], 1) ; for(i = 1 ; i <= m ; i ++) { scanf("%d %d %d", &l, &r, &k) ; ans = query(T[r], T[l-1], 1, cnt, k) ; printf("%d\n", nar[ans]) ;//离散后的数组 } } } 五、KD树 #define N 50005 #define MID(x,y) ( (x + y)>>1 ) using namespace std ; typedef long long LL ; struct Point{ int x[5]; LL dis; Point(){ for(int i = 0 ; i < 5 ; i++) x[i] = 0 ; dis = 9223372036854775807LL ; } friend bool operator < (const Point &a, const Point &b) { return a.dis < b.dis ; } }; priority_queue <Point, vector<Point> > res ; LL dist2(const Point &a, const Point &b, int k) { //距离的平方,开根号很耗时,能不开就不开 LL ans = 0; for (int i = 0; i < k; i++) //一开始这儿写的i < 5,WA了N次。。。原本以为只要初始值设0就无所谓, ans += (a.x[i] - b.x[i]) * (a.x[i] - b.x[i]); //但发现Point有个全局变量,在多case下会出错。。。 return ans; } int ddiv; bool cmpX(const Point &a, const Point &b){return a.x[ddiv] < b.x[ddiv];} struct KDTree { Point p ; //空间内的点 int Div ; //记录区间是按什么方式划分(分割线平行于x轴还是y轴, ==1平行y轴切;==0平行x轴切) int k; //维数 int m; //近邻 int getDiv(int l, int r) { //寻找区间跨度最大的划分方式 map <int, int> ms; int minx[5],maxx[5]; for (int i = 0; i < k; i++) { ddiv = i; minx[i] = min_element(p + l, p + r + 1, cmpX)->x[i]; maxx[i] = max_element(p + l, p + r + 1, cmpX)->x[i]; ms[maxx[i] - minx[i]] = i; } map <int ,int>::iterator pm = ms.end(); pm--; return pm->second; } void build(int l, int r) { //记得先把p备份一下。 if (l > r) return; int mid = MID(l,r); Div[mid] = getDiv(l,r); ddiv = Div[mid]; nth_element(p + l, p + mid, p + r + 1, cmpX); build(l, mid - 1); build(mid + 1, r); } void findk(int l, int r, Point a) {//k(m)近邻,查找k近点的平方距离 if (l > r) return; int mid = MID(l,r); LL dist = dist2(a, p[mid], k); if (dist >= 0) { p[mid].dis = dist; res.push(p[mid]); while ((int)res.size() > m) res.pop(); } LL d = a.x[Div[mid]] - p[mid].x[Div[mid]]; int l1, l2, r1, r2; l1 = l , l2 = mid + 1; r1 = mid - 1, r2 = r; if (d > 0) swap(l1, l2), swap(r1, r2); findk(l1, r1, a); if ((int)res.size() < m || d*d < res.top().dis ) findk(l2, r2, a); } }; Point pp ; KDTree kd; int solve(){ for (int i = 0; i < n; i++) for (int j = 0; j < kd.k; j++) { scanf("%d", &pp[i].x[j]); kd.p[i] = pp[i]; } kd.build(0, n - 1); int t = 10 ; while(t--) { Point a; for (int i = 0; i < kd.k; i++)scanf("%d", &a.x[i]); scanf("%d", &kd.m); kd.findk(0, n - 1, a); printf("the closest %d points are:\n", kd.m); Point ans[11]; for (int i = 0; !res.empty(); i++) { ans[i] = res.top(); res.pop(); } for (int i = kd.m - 1; i >= 0; i--) { for (int j = 0; j < kd.k - 1; j++) printf("%d ", ans[i].x[j]); printf("%d\n", ans[i].x[kd.k - 1]); } } 六、最远manhattan距离 int query(int rt, int p, int s) //维护每个状态的最大值、最小值。 void getTable(int pos){//每个点有sta个状态 int i, j, t ; for(i = 0 ; i < sta ; i ++) { t = i ; tmp[i] = 0 ; for(j = 1 ; j <= k ; j ++) { if(t&1) tmp[i] += ar[pos].x[j] ; else tmp[i] -= ar[pos].x[j] ; t >>= 1 ; } } } int solve(){ sta = 1<<k ; //K维平面 build(1, 1, q) ;//将每个点的sta个状态插入树中 cnt = 0 ; for(i = 1 ; i <= q ; i ++) { if(cnt < 2){puts("0") ;continue ; } int ans = 0 ; for(j = 0 ; j < sta ; j ++) { mxs = query(1, j, 1) ; //查询最大值; mns = query(1, j, 0) ; //查询最小值; ans = ans > mxs - mns ? ans : mxs-mns ; } printf("%d\n", ans) ; } 七、LCA & RMQ & 树状数组 /*****************************LCA*******************************/ struct QNode{ int from, to, next, no ; }qe[MAXN]; int cnt ; int qhead[MAXN], pre[MAXN], LCA[MAXN] ; inline void addQEdge(int a,int b,int c){ qe[++cnt].from = a ; qe[cnt].to = b ; qe[cnt].next = qhead[a] ; qe[cnt].no = c ; qhead[a] = cnt; } int find(int x){ if(x != pre[x]) pre[x]=find(pre[x]); return pre[x]; } void tarjan(int u){ int j, v ; pre[u] = u ; for(j = qhead[u] ; j != -1 ; j = qe[j].next) { v = qe[j].to; LCA[qe[j].no] = find(v) ; } for(j = head[u] ; j != -1 ;j = e[j].next) { v = e[j].to ; tarjan(v) ; pre[v] = u ; } } /*****************************RMQ*******************************/ int mn[MAXN][18] ; void rmq_init(int num){ int i , j ; for(j = 1 ; j <= num ; j ++ ) mn[j][0] = height[j] ; int m = floor(log((double)num)/log(2.0)) ; for(i = 1 ; i <= m ; i ++ ) { for(j = num ; j > 0 ; j -- ) { mn[j][i] = mn[j][i-1] ; if(j+(1<<(i-1)) <= num) mn[j][i] = min( mn[j][i] , mn[j+(1<<(i-1))][i-1]) ; } } } int rmq(int l,int r){ int m = floor(log((double)(r-l+1))/log(2.0)) ; int a = min(mn[l][m], mn[r-(1<<m)+1][m] ) ; return a ; } /*****************************树状数组*******************************/ int Lowbit(int t){ //求最小幂2^k return t&(-t) ; } int Sum(int end) { //求前n项和 int sum = 0 ; while(end > 0) { sum += c[end]; end -= Lowbit(end); } return sum; } void plus(int pos , int n, int num){ //对某个元素进行加法操作 while(pos <= n) { c[pos] += num; pos += Lowbit(pos); } } 八、划分树 int SU[100001]; int U[21][100001]; int toL[21][100001]; int n,m,a,b,k,t; inline int cmp(const void *a,const void *b){return *((int *)a) - *((int *)b) ;} void buildtree(int l,int r,int d){ int i ; if (l==r) return; int mid = (l+r)>>1 , nowl = l , nowr = mid+1 , midtol = 0 ; for (i = mid ;i>=l && SU[i] == SU[mid] ; i--) ++midtol ; for (i = l ; i <= r ; i++) { toL[d][i] = i==l ? 0 : toL[d][i-1]; if (U[d][i] < SU[mid]) { U[d+1][nowl++] = U[d][i]; ++toL[d][i]; } else if (U[d][i]==SU[mid] && midtol) { U[d+1][nowl++] = U[d][i]; ++toL[d][i]; --midtol; } else U[d+1][nowr++] = U[d][i]; } buildtree(l,mid,d+1); buildtree(mid+1,r,d+1); } int answer(int a,int b,int k){ int l = 1,r = n,d = 0; int ls,rs,mid; while (a != b) { ls = a==l ? 0 : toL[d][a-1]; rs = toL[d][b]; mid = (l+r)>>1; if (k <= rs - ls) { a = l+ls; b = l+rs-1; r = mid; } else { a = mid+1+a-l-ls; b = mid+1+b-l-rs; k -= rs-ls; l = mid+1; } ++d; } return U[d][a]; } int solve(){ for (i=1;i<=n;i++) { scanf("%d",&t); SU[i]=U[0][i]=t; } sort(SU+1, SU+1+n) ; buildtree(1 , n , 0 ); printf("%d\n",answer(a, b, k ) ); }
View Code
相关文章推荐
- 数据结构代码整理(2)
- 数据结构面试整理(2)
- [ACM] 最短路算法整理(bellman_ford , SPFA , floyed , dijkstra 思想,步骤及模板)
- 【数据结构第三周】树知识点整理(上)
- python数据结构(整理)
- [ACM] POJ 2186 Popular Cows (强连通分量,Kosaraju算法知识整理)
- 数据结构 && ACM :比较两棵树是否相等。
- 数据结构部分考点整理
- ACM 数据结构 线段树 HDU 1698Just a Hook
- 国家队ACM论文分类整理(转载)
- 2017年ACM模板(常用)弱渣整理 四、动态规划
- Python常见数据结构整理
- 数据结构(C#版)概念整理
- 算法整理篇之:数据结构(0)
- ACM-ICPC 常用算法刷题网站整理
- ACM/lCPC要求的数据结构知识点
- ACM算法整理(不断补充ing)
- [心得]算法和数据结构Ellis Horowitz大神知识整理
- 面试小结三:关于算法数据结构的面试题整理(待续)
- 常见的数据结构和算法整理