整体二分
来源:互联网 发布:淘宝网加肥加大男装 编辑:程序博客网 时间:2024/04/25 21:13
很好的一篇入门:
http://www.cnblogs.com/zig-zag/archive/2013/04/18/3027707.html
跟时间分治一样,我们需要把握好一个序。
它的适用范围一般是可以二分的题目,例如区间k大之类恶心的东西
你说带修改k大?树上带修改k大?主席树上啊……孩子醒醒吧,树套树你会崩溃的尤其还不是一般的线段树
Zig-Zag神牛那篇讲的是带修改的区间k大,我就无聊说说跟它不完全一样的树上k大(虽然其实差不多)
好吧还是差很多的,蒟蒻只能yy出一个很不靠谱的方法……
首先,入口是solve(l,r,L,R)表示待处理区间为Seq[l]~Seq[r],答案范围为L,R
类似区间k大,我们在小于MID的点+1,求u到v路径上的和,便是当前有多少数小于mid
至于怎么搞……树链剖分或者LCT都行了(大家散吧博主傻逼我去写树套树了~喂别跑了LCT还是比树套树好写的!!!!!)
然后抓住一个序的问题,将小于MID的修改,以及cur没有到所需k的查询,加入QL队列,否则加入QR队列。
切记维护一个序序序序!!!!
你说代码,没有!!!
update:无聊还是写了下,顺便练一下代码能力,暂时没过,不过问题不大
#include <cstdio>#include <vector>#include <algorithm>using namespace std;const int MAXN = 1001;const int MAXM = 1001; struct Node *null;struct Node{int v,sum;int size;Node *ch[2],*f;void maintain(){size = 1+ch[0]->size+ch[1]->size, sum = v+ch[0]->sum+ch[1]->sum;}bool check(){return f != null && (f->ch[0] == this || f->ch[1] == this);}int d(){return f->ch[1] == this ? 1 : 0;}void setc(Node *c,int d){ch[d] = c, c->f = this;}Node (){ch[0] = ch[1] = f = null, size = 1, v = sum = 0;}Node (int x){ch[0] = ch[1] = f = NULL, size = 0, v = sum = 0;};};struct Q{int oper,u,v,k,id,cur;};int n,m,cnt;int id[MAXN],idx[MAXN],ans[MAXN];int temp[MAXM];Q Seq[MAXM],QL[MAXM],QR[MAXM];Node *p[MAXN];vector <int> G[MAXN];inline void READ(int &x){char c;x = 0;do c = getchar(); while (c < '0' || c > '9');do x = x*10+c-48, c = getchar(); while (c >= '0' && c <= '9');}bool cmp(int x,int y){return id[x] < id[y];}void rotate(Node *p){Node *x = p->f;int d = p->d();if (!x->check()) p->f = x->f;else x->f->setc(p,x->d());x->setc(p->ch[d^1],d);p->setc(x,d^1);x->maintain();}void Splay(Node *p){while (p->check()){Node *x = p->f;if (!x->check()) rotate(p);else p->d() == x->d() ? (rotate(x),rotate(p)) : (rotate(p),rotate(p));}p->maintain();}void Access(Node *p){for (Node *q = null; p != null; p = p->f){Splay(p);p->setc(q,1);(q = p)->maintain();}}inline int query(Node *u,Node *v){Access(u);int ans = 0;for (Node *q = null; v != null; v = v->f){Splay(v);if (v->f == null) ans = q->sum+v->sum;v->setc(q,1);(q = v)->maintain();}return ans;}inline void modify(Node *u,int delta){u->v += delta;u->sum += delta;}void dfs(int u,int fa){p[u]->f = p[fa];for (int i=0;i<G[u].size();i++) if (G[u][i] != fa) dfs(G[u][i],u);}void solve(int l,int r,int L,int R){if (L == R) {for (int i=l;i<=r;i++) if (Seq[i].oper == 1) ans[Seq[i].id] = L;return;}int MID = (L+R)/2;for (int i=l;i<=r;i++){if (Seq[i].oper == 1) temp[i] = query(p[Seq[i].u],p[Seq[i].v]);else if (Seq[i].v <= MID) modify(p[Seq[i].u],1);}for (int i=l;i<=r;i++) if (Seq[i].oper == 2 && Seq[i].v <= MID) modify(p[Seq[i].u],-1);int LenL = 0, LenR = 0;for (int i=l;i<=r;i++){if (Seq[i].oper == 1){if (temp[i]+Seq[i].cur >= Seq[i].k) QL[++LenL] = Seq[i];else{Seq[i].cur += temp[i];QR[++LenR] = Seq[i];}}else {if (Seq[i].v <= MID) QL[++LenL] = Seq[i];else QR[++LenR] = Seq[i];}}cnt = l-1;for (int i=1;i<=LenL;i++) Seq[++cnt] = QL[i];for (int i=1;i<=LenR;i++) Seq[++cnt] = QR[i];solve(l,l+LenL-1,L,MID);solve(l+LenL,r,MID+1,R); }int main(){null = new Node(1);READ(n);READ(m);for (int i=1;i<=n;i++) READ(id[i]),idx[i] = i;sort(idx+1,idx+n+1,cmp);for (int i=1;i<=n;i++) Seq[++cnt] = (Q){2,idx[i],i,0,0,0};for (int i=1;i<=n;i++) p[i] = new Node();p[0] = null;for (int i=1;i<n;i++){int u,v;READ(u);READ(v);G[u].push_back(v);G[v].push_back(u);}dfs(1,0);for (int i=1;i<=m;i++){int l,r,k;scanf("%d%d%d",&l,&r,&k);Seq[++cnt] = (Q){1,l,r,k,i,0};} solve(1,cnt,1,n);for (int i=1;i<=m;i++) printf("%d\n",id[idx[ans[i]]]);return 0;}
0 0
- 整体二分
- 整体二分
- 整体二分
- 整体二分
- 整体二分
- 整体二分
- 整体二分(二分进阶)
- BZOJ1901【整体二分】
- BZOJ2527【整体二分】
- 整体二分入门
- 复习一下整体二分
- 【bzoj2527】Meteors【整体二分】
- POJ 2104【整体二分】
- 整体二分小结
- 【辅助算法】整体二分
- 整体二分初步
- POJ2104 整体二分、树套树
- hdu5808 整体二分
- BSP中几个重要文件的修改
- ROW_NUMBER (Transact-SQL)
- 什么是“集合运算”
- URLRewrite初试
- 互斥量的同步(Mutex)
- 整体二分
- 系统下多数据库用户配置
- java 发起http请求并获取结果(json)
- 怪物的生成 攻击和掉落金币
- Friends' Friends
- 杭电2017最简字符串
- S3C2440 VXWORKS移植笔记
- LeetCode - Maximal Rectangle 题解
- typedef void (*funcptr)()