acm数据结构整理
- 一、区间划分
- //区间划分+持久化并查集:区间连通情况统计。
- 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 + ;
- for(i = ; i <= n ; i ++) e[i].clear() ;
- }
- /*********************持久化并查集**********************************/
- void solve()//区间划分{
- int i = , j, k, l, r ;
- sort(ask+, ask++q, comp) ;
- while(i <= q) //询问
- {
- k = ask[i].km ;
- for(; i <= q && ask[i].km == k && ask[i].l > (k-)*ms ; i ++) //处理区间小于ms的询问
- ans[ask[i].no] = bfAnswer(i) ;
- if(i > q || ask[i].km != k ) //全部为小区间
- continue ;
- r = (k-)*ms ; //最右端
- initSet(lp, , r) ; //初始化并查集 ;
- for(j = ; j <= r ; j ++) vis[j] = ;
- while(i <= q && ask[i].km == k ) //求解第k块的所有大询问;
- {
- l = ask[i].l ;
- for(j = r ; j >= l ; j -- ) //加入顶点j
- addVex(lp, j, (k-)*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-)*ms+, 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] == -)
- {
- 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] == -)
- {
- 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 = ;
- getBinary(x) ;
- j = dig[i--] ;
- if(j) ans += root[rt].sum ;
- if(root[rt].next[j] == -) return ans ;
- p = root[rt].next[j] ;
- while(i)
- {
- j = dig[i--] ;
- if(j) ans += pool[p].sum ;
- if(pool[p].next[j] == -) 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+ ;
- for(i = ; i <= mg ; i ++) root[i].set() ;
- for(i = ; i <= n ; i ++)
- {
- k = (i-)/size + ;
- DT_insert(k, ar[i], ) ;
- }
- bs = *size ;
- bmg = n/bs ;
- bmg = bmg*bs == n ? bmg : bmg + ;
- for(i = ; i <= bmg+ ; i ++) root[MAXS+i].set() ;
- for(i = ; i <= n ; i ++)
- {
- k = (i-)/bs + ;
- DT_insert(MAXS+k, ar[i], ) ;
- }
- }
- int DT_query(int l, int r, int x){
- int i, k, ans = , bk ;
- k = (l-)/size + ;
- k = size*(k-)+ == l ? k : k + ; //前
- for(i = l ; i <= r && i < (k-)*size+ ; i ++) ans = ar[i] < x ? ans+ : ans ;
- for(; i <= r && r-i+ >= size && (k% != ) ; i += size, k ++) //小块
- ans += DT_count(k, x) ;
- for(bk = (k-)/+ ; i <= r && r-i+ >= bs ; i += bs, bk ++, k += )
- ans += DT_count(MAXS+bk, x) ;//大块
- for(; i <= r && r-i+ >= size ; i += size, k ++) //小块
- ans += DT_count(k, x) ;
- for(; i <= r ; i ++) ans = ar[i] < x ? ans+ : ans ;
- return ans ;
- }
- 三、树链剖分
- . 树上区间[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 >= )
- {
- pool[p] = pool[pre] ;
- j = x&(<<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] = ; son[u] = ;
- for(i = head[u] ; i != - ; i = e[i].next )
- {
- to = e[i].to ;
- if(to != fa[u])
- {
- fa[to] = u ;
- dep[to] = dep[u] + ;
- 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 != - ; i = e[i].next)
- {
- int to = e[i].to ;
- if(to != fa[u] && to != son[u]) cutLink(to, to) ;
- }
- }
- void buildTree(){
- dep[] = ;
- cnt = fa[] = siz[] = ;
- DFS() ;
- cutLink(, ) ;
- int i ;
- for(i = ; i <= n ; i ++) val[w[i]] = ar[i] ;
- pool[].set() ;
- dcnt = T[] = ;
- for(i = ; i <= cnt ; i ++) insert(T[], val[i]) ;
- for(i = ; i <= cnt ; i ++) addNumber(T[i-], T[i], i, val[i]) ;//持久化思
- }
- int getAns(int u, int v, int x){
- int ans = , 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) ;
- }
- . BFS实现建树
- int leaf[MAXN], ns[MAXN], ct[MAXN];
- void BFS(int rt){
- int i, h = , t = , l = , r = ;
- int u, to ;
- que[t++] = rt ;
- for(i = ; i <= n ; i ++)
- {
- siz[i] = ;
- ct[i] = ns[i] = son[i] = ;
- }
- while (h < t) // calculate the dep.
- {
- u = que[h++] ;
- for(i = head[u] ; i != - ; i = e[i].next)
- {
- to = e[i].to ;
- if(to != fa[u])
- {
- ns[u] ++ ;
- fa[to] = u ;
- dep[to] = dep[u] + ;
- que[t++] = to ;
- }
- }
- }
- for(i = ; i <= n ; i ++) if(ns[i] == ) 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 = ;
- que[t++] = rt ;
- siz[] = ;
- while (h < t)
- {
- u = que[h++] ;
- for(i = head[u] ; i != - ; 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 = , t = ;
- 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 != - ; 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 != - ; i = e[i].next)
- {
- to = e[i].to ;
- if(to != fa[u] && to != son[u]) que[t++] = to ;
- }
- }
- }
- . 非直接合并查询:树上最长上升子序列
- /*********************线段树成段更新最长上升子序列*************************/
- 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:) ;
- L[step].rx = L[rson].rx + ((L[rson].rx==L[rson].len &&val[L[rson].left] > val[L[lson].right])?L[lson].rx:) ;
- 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):);
- L[step].dlx = L[lson].dlx + ( (L[lson].dlx == L[lson].len && val[L[rson].left] < val[L[lson].right]) ? L[rson].dlx : );
- L[step].drx = L[rson].drx + ((L[rson].drx == L[rson].len && val[L[rson].left] < val[L[lson].right]) ? L[lson].drx : ) ;
- 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) : ) ;
- }
- void build(int step,int l,int r){
- L[step].left=l;
- L[step].right=r;
- L[step].len = r-l+ ;
- L[step].mid=(l+r)/;
- if(l==r)
- {
- L[step].lx = L[step].rx = L[step].mx = ;
- L[step].dlx =L[step].drx = L[step].dmx = ;
- 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 : ) ;
- L[ar].rx = L[r].rx + ((L[r].rx==L[r].len && val[L[r].left]
- > val[L[l].right]) ? L[l].rx : ) ;
- 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):);
- L[ar].dlx = L[l].dlx + ((L[l].dlx == L[l].len && val[L[r].left]
- < val[L[l].right]) ? L[r].dlx : );
- L[ar].drx = L[r].drx + ((L[r].drx == L[r].len && val[L[r].left]
- < val[L[l].right]) ? L[l].drx : ) ;
- 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) : ) ;
- 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+,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 = ;
- ans = max(tmp, ans) ;
- return ans ;
- }
- int getAns(int u, int v){
- if(u == v) return L[query(, w[u], w[u])].mx ;
- int tu = top[u], tv = top[v] ;
- int ar, tr, ur, vr ;
- scnt = *cnt +;
- ar = ++scnt ; ur = - ; vr = - ;
- while (tu != tv)
- {
- if(dep[tu] > dep[tv])//calculate the link tu -> u.
- {
- tr = query(, w[tu], w[u]) ;
- if(ur == -) ur = tr ;
- else {
- ++scnt ;
- unionNode(tr, ur, scnt); //tr is left node.
- ur = scnt ;
- }
- u = fa[tu] ; tu = top[u] ;
- }
- else {
- tr = query(, w[tv], w[v]) ;
- if(vr == -) 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(, w[v], w[u]) ;
- if(ur == -) ur = tr ;
- else {
- scnt ++ ;
- unionNode(tr, ur, scnt) ;
- ur = scnt ;
- }
- u = v ;
- }
- else {
- tr = query(, w[u], w[v]) ;
- if(vr == -) vr = tr ;
- else {
- ++scnt ;
- unionNode(tr, vr, scnt) ;
- vr = scnt ;
- }
- v = u ;
- }
- if(ur == -) return L[vr].mx ;
- else if(vr == -) return L[ur].dmx ;
- return unionAns(ur, vr) ; // calculate the answer of u->v
- }
- . 树上最大字段和
- /*********************线段树最大子段和*************************/
- inline void Up(int rt){
- sum[rt] = sum[rt<<] + sum[rt<<|] ;
- lx[rt] = max(lx[rt<<|], lx[rt<<] + sum[rt<<|]) ;
- rx[rt] = max(rx[rt<<], rx[rt<<|] + sum[rt<<]) ;
- mx[rt] = max(mx[rt<<], mx[rt<<|]) ;//不合并
- mx[rt] = max(mx[rt], lx[rt<<] + rx[rt<<|]) ; //合并
- }
- inline void Down(int rt, int L, int R){
- if(d[rt] != INF)
- {
- int x = d[rt] ;
- int mid = (L+R) >> ;
- d[rt] = INF ;
- d[rt<<] = d[rt<<|] = x ;
- sum[rt<<] = (LL)x*(mid-L+) ;
- sum[rt<<|] = (LL)x*(R-mid) ;
- lx[rt<<] = rx[rt<<] = mx[rt<<] = x > ? sum[rt<<] : ;
- lx[rt<<|] = rx[rt<<|] = mx[rt<<|] = x > ? sum[rt<<|] : ;
- }
- }
- 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+)*x ;
- lx[rt] = rx[rt] = mx[rt] = x > ? sum[rt] : ;
- 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<<, L, mid, l, mid) ;
- int y = query(rt<<|, mid+, R, mid+, 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(, , cnt, w[u], w[u]) ;
- int tu = top[u], tv = top[v] ;
- int ar, tr, ur, vr ;
- scnt = *cnt +;
- ar = ++scnt ; ur = - ; vr = - ;
- while (tu != tv)
- {
- if(dep[tu] > dep[tv])//calculate the link tu -> u.
- {
- tr = query(, , cnt, w[tu], w[u]) ;
- if(ur == -) ur = tr ;
- else {
- ++scnt ;
- unionNode(tr, ur, scnt); //tr is left node.
- ur = scnt ;
- }
- u = fa[tu] ; tu = top[u] ;
- }
- else {
- tr = query(, , cnt, w[tv], w[v]) ;
- if(vr == -) 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(, , cnt, w[v], w[u]) ;
- if(ur == -) ur = tr ;
- else {
- scnt ++ ;
- unionNode(tr, ur, scnt) ;
- ur = scnt ;
- }
- u = v ;
- }
- else {
- tr = query(, , cnt, w[u], w[v]) ;
- if(vr == -) vr = tr ;
- else {
- ++scnt ;
- unionNode(tr, vr, scnt) ;
- vr = scnt ;
- }
- v = u ;
- }
- if(ur == -) return vr ;
- else if(vr == -) 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] = ;
- 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 >> ;
- if(mid >= i ) updata(ls[rt], ls[pre], l, mid, i, v) ;
- else updata(rs[rt], rs[pre], mid+, 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 >> ;
- if(t >= k) return query(ls[R], ls[L], l, mid, k) ;
- else return query(rs[R], rs[L], mid+, r, k-t) ;
- }
- /***************************************************************/
- void solve(){
- sort(ord+, ord++n, comp) ;
- cnt = rk[ord[]] = ;
- nar[cnt] = ar[ord[]] ;
- for(i = ; i <= n ; i ++)
- {
- if(ar[ord[i]] != ar[ord[i-]])
- {
- rk[ord[i]] = ++cnt ;
- nar[cnt] = ar[ord[i]] ;
- }
- else rk[ord[i]] = cnt ;
- }
- tot = ;
- build(T[], , cnt) ;
- for(i = ; i <= n ; i ++) updata(T[i], T[i-], , cnt, rk[i], ) ;
- for(i = ; i <= m ; i ++)
- {
- scanf("%d %d %d", &l, &r, &k) ;
- ans = query(T[r], T[l-], , 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[];
- LL dis;
- Point(){
- for(int i = ; i < ; i++) x[i] = ;
- 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 = ;
- for (int i = ; 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[N]; //空间内的点
- int Div[N];
- //记录区间是按什么方式划分(分割线平行于x轴还是y轴, ==1平行y轴切;==0平行x轴切)
- int k; //维数
- int m; //近邻
- int getDiv(int l, int r) { //寻找区间跨度最大的划分方式
- map <int, int> ms;
- int minx[],maxx[];
- for (int i = ; i < k; i++)
- {
- ddiv = i;
- minx[i] = min_element(p + l, p + r + , cmpX)->x[i];
- maxx[i] = max_element(p + l, p + r + , 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 + , cmpX);
- build(l, mid - );
- build(mid + , 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 >= )
- {
- 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 + ;
- r1 = mid - , r2 = r;
- if (d > )
- 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[N];
- KDTree kd;
- int solve(){
- for (int i = ; i < n; i++)
- for (int j = ; j < kd.k; j++)
- {
- scanf("%d", &pp[i].x[j]);
- kd.p[i] = pp[i];
- }
- kd.build(, n - );
- int t = ;
- while(t--)
- {
- Point a;
- for (int i = ; i < kd.k; i++)scanf("%d", &a.x[i]);
- scanf("%d", &kd.m);
- kd.findk(, n - , a);
- printf("the closest %d points are:\n", kd.m);
- Point ans[];
- for (int i = ; !res.empty(); i++)
- {
- ans[i] = res.top();
- res.pop();
- }
- for (int i = kd.m - ; i >= ; i--)
- {
- for (int j = ; j < kd.k - ; j++)
- printf("%d ", ans[i].x[j]);
- printf("%d\n", ans[i].x[kd.k - ]);
- }
- }
- 六、最远manhattan距离
- int query(int rt, int p, int s) //维护每个状态的最大值、最小值。
- void getTable(int pos){//每个点有sta个状态
- int i, j, t ;
- for(i = ; i < sta ; i ++)
- {
- t = i ;
- tmp[i] = ;
- for(j = ; j <= k ; j ++)
- {
- if(t&) tmp[i] += ar[pos].x[j] ;
- else tmp[i] -= ar[pos].x[j] ;
- t >>= ;
- }
- }
- }
- int solve(){
- sta = <<k ; //K维平面
- build(, , q) ;//将每个点的sta个状态插入树中
- cnt = ;
- for(i = ; i <= q ; i ++)
- {
- if(cnt < ){puts("") ;continue ; }
- int ans = ;
- for(j = ; j < sta ; j ++)
- {
- mxs = query(, j, ) ; //查询最大值;
- mns = query(, j, ) ; //查询最小值;
- 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 != - ; j = qe[j].next)
- {
- v = qe[j].to;
- LCA[qe[j].no] = find(v) ;
- }
- for(j = head[u] ; j != - ;j = e[j].next)
- {
- v = e[j].to ;
- tarjan(v) ;
- pre[v] = u ;
- }
- }
- /*****************************RMQ*******************************/
- int mn[MAXN][] ;
- void rmq_init(int num){
- int i , j ;
- for(j = ; j <= num ; j ++ ) mn[j][] = height[j] ;
- int m = floor(log((double)num)/log(2.0)) ;
- for(i = ; i <= m ; i ++ )
- {
- for(j = num ; j > ; j -- )
- {
- mn[j][i] = mn[j][i-] ;
- if(j+(<<(i-)) <= num)
- mn[j][i] = min( mn[j][i] , mn[j+(<<(i-))][i-]) ;
- }
- }
- }
- int rmq(int l,int r){
- int m = floor(log((double)(r-l+))/log(2.0)) ;
- int a = min(mn[l][m], mn[r-(<<m)+][m] ) ;
- return a ;
- }
- /*****************************树状数组*******************************/
- int Lowbit(int t){ //求最小幂2^k
- return t&(-t) ;
- }
- int Sum(int end) { //求前n项和
- int sum = ;
- while(end > )
- {
- 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[];
- int U[][];
- int toL[][];
- 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)>> , nowl = l , nowr = mid+ , midtol = ;
- for (i = mid ;i>=l && SU[i] == SU[mid] ; i--) ++midtol ;
- for (i = l ; i <= r ; i++)
- {
- toL[d][i] = i==l ? : toL[d][i-];
- if (U[d][i] < SU[mid])
- {
- U[d+][nowl++] = U[d][i];
- ++toL[d][i];
- }
- else if (U[d][i]==SU[mid] && midtol)
- {
- U[d+][nowl++] = U[d][i];
- ++toL[d][i];
- --midtol;
- }
- else U[d+][nowr++] = U[d][i];
- }
- buildtree(l,mid,d+);
- buildtree(mid+,r,d+);
- }
- int answer(int a,int b,int k){
- int l = ,r = n,d = ;
- int ls,rs,mid;
- while (a != b)
- {
- ls = a==l ? : toL[d][a-];
- rs = toL[d][b];
- mid = (l+r)>>;
- if (k <= rs - ls)
- {
- a = l+ls;
- b = l+rs-;
- r = mid;
- }
- else {
- a = mid++a-l-ls;
- b = mid++b-l-rs;
- k -= rs-ls;
- l = mid+;
- }
- ++d;
- }
- return U[d][a];
- }
- int solve(){
- for (i=;i<=n;i++)
- {
- scanf("%d",&t);
- SU[i]=U[][i]=t;
- }
- sort(SU+, SU++n) ;
- buildtree( , n , );
- printf("%d\n",answer(a, b, k ) );
- }
acm数据结构整理的更多相关文章
- ACM数据结构-并查集
ACM数据结构-并查集 并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合 ...
- 转 Python常见数据结构整理
http://www.cnblogs.com/jeffwongishandsome/archive/2012/08/05/2623660.html Python常见数据结构整理 Python中常见的数 ...
- ACM数据结构-树状数组
模板: int n; int tree[LEN]; int lowbit(int x){ return x&-x; } void update(int i,int d){//index,del ...
- ACM数据结构相关资料整理【未完成,待补充】
在网上总是查不到很系统的练ACM需要学习的数据结构资料,于是参考看过的东西,自己整理了一份. 能力有限,欢迎大家指正补充. 分类主要参考<算法竞赛入门经典训练指南>(刘汝佳),山东大学数据 ...
- Java数据结构整理(一)
ava数据结构内容整理关键字: 数据结构 Collection:List.SetMap:HashMap.HashTable如何在它们之间选择一.Array , ArraysJava所有“存储及随机访问 ...
- ACM算法整理(不断补充ing)
动态规划 1.背包问题 (1)01背包 ,n) DFR(v,V,C[i]) F[v]=max(F[v],F[v-C[i]]+W[i]); } //初始化时 //若背包不一定装满F全初始化为0 //若装 ...
- (数据结构整理)NJUPT1054
这一篇博客以一些OJ上的题目为载体,整理一下数据结构.会陆续的更新. .. 我们都知道,数据结构的灵活应用有时能让简化一些题目的解答. 一.栈的应用 1.NJUPT OJ 1054(回文串的推断) 回 ...
- redis数据结构整理(二)
摘要: 1.各个数据结构的应用举例 1.1 String类型应用举例 1.2List类型应用举例 1.3Set类型应用举例 1.4Sorted Set类型应用举例 1.5Hash类型应用举例 内容: ...
- redis数据结构整理(一)
摘要: 0.redis安装 1.redis的常用数据结构类型 1.1 String 1.2 List 1.3 Set 1.4 Sorted Set 1.5 Hash 2.redis是单进程单 ...
随机推荐
- VC中不同类型DLL及区别
1. DLL的概念可以向程序提供一些函数.变量或类. 静态链接库与动态链接库的区别:(1)静态链接库与动态链接库都是共享代码的方式.静态链接库把最后的指令都包含在最终生成的EXE文件中了:动态链接库不 ...
- linux Ubuntu12 设置root用户登录图形界面
Ubuntu 12.04默认是不允许root登录的,在登录窗口只能看到普通用户和访客登录.以普通身份登陆Ubuntu后我们需要做一些修改,普通用户登录后,修改系统配置文件需要切换到超级用户模式,在终端 ...
- 解决ubuntu中vi不能正常使用方向键与退格键的问题
方案一: 问题: ubuntu中vi在编辑状态下方向键不能用,还有回格键不能删除等我们平时习惯的一些键都不能使用. 解决办法: 可以安装vim full版本,在full版本下键盘正常,安装好后同样使用 ...
- Android隐藏输入法键盘(hideSoftInputFromInputMethod没有效果)
在个别时候,需要强制隐藏Android输入法键盘,如当前键盘正在显示,这个时候点击了侧滑面板,就要强制隐藏输入法键盘.网上常见的方法有: 1. InputMethodManager imm = (In ...
- 安装Hadoop系列 — 安装Hadoop
安装步骤如下: 1)下载hadoop:hadoop-1.0.3 http://archive.apache.org/dist/hadoop/core/hadoop-1.0.3/ 2)解压文 ...
- js setTimeout深度递归后完成回调
setTimout原型: iTimerID = window.setTimeout(vCode, iMilliSeconds [, sLanguage]) setTimeout有两种形式 se ...
- poj 3009 Curling 2.0( dfs )
题目:http://poj.org/problem?id=3009 参考博客:http://www.cnblogs.com/LK1994/ #include <iostream> #inc ...
- 大四实习准备2_java异常处理_android控件练习
2015-4-24 Java 异常处理 可以有多个catch;ArrayIndexOutOfBoundsException类是Exception类的子类RuntimeException类的一个间接子类 ...
- 中南大学oj 1317 Find the max Link 边权可以为负的树上最长路 树形dp 不能两遍dfs
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1317经典问题:树上最长路,边权可以为负值的,树形dp,不能用两边dfs.反例:5 41 2 22 ...
- jquery图片轮播-插件
更新内容: 1. 页面结构和css样式必定类似下边放置 2. 点击左右按钮,实现左右滑动. 3. 这一般用于多个图片轮播使用,简化并优化代码. 若因不同需求,均可自行将插件scrollimgplus. ...