我现在才开始刷 QTREE 是不是太弱了?算了不管他……

QTREE: 树链剖分裸题(据说 lct 会超时……该说是真不愧有 spoj 的气息吗?)

 #include <cstdio>
#include <cstring>
const int sizeOfPoint=;
const int sizeOfEdge=;
const int sizeOfNode=; inline void swap(int & , int & );
inline int max(int, int);
inline char getch();
inline int getint();
inline void putint(int); struct edge {int index, point, dist; edge * next;};
edge memory_edge[sizeOfEdge], * port_edge=memory_edge;
inline edge * newedge(int, int, int, edge * );
inline void link(int, int, int, int); struct node {int c; node * l, * r;};
node memory_node[sizeOfNode], * port_node=memory_node;
inline node * newnode();
node * build(int, int);
void update(node * , int, int, int, int);
int query(node * , int, int, int, int); edge * e[sizeOfPoint];
int d[sizeOfPoint], f[sizeOfPoint], s[sizeOfPoint];
int num, idx[sizeOfPoint], son[sizeOfPoint], top[sizeOfPoint];
void dfs(int);
void divide(int, int);
inline int query(int, int); int c, n;
int a[sizeOfPoint], k[sizeOfPoint];
node * t;
inline void clear(); int main()
{
for (c=getint();c;c--)
{
clear(); n=getint();
for (int i=;i<n;i++)
{
int u=getint(), v=getint(), d=getint();
link(i, u, v, d);
}
dfs();
divide(, ); t=build(, n);
for (int i=;i<=n;i++)
update(t, , n, idx[i], a[i]); while (true)
{
char ch=getch();
if (ch=='D') break;
else if (ch=='Q')
{
int u=getint(), v=getint();
putint(query(u, v));
}
else if (ch=='C')
{
int u=getint(), v=getint();
a[k[u]]=v;
update(t, , n, idx[k[u]], v);
}
}
} return ;
} inline void swap(int & x, int & y)
{
int t=x; x=y; y=t;
}
inline int max(int x, int y)
{
return x>y?x:y;
}
inline char getch()
{
register char ch;
do ch=getchar(); while (ch!='Q' && ch!='C' && ch!='D');
return ch;
}
inline int getint()
{
register int num=;
register char ch=, last;
do last=ch, ch=getchar(); while (ch<'' || ch>'');
do num=num*+ch-'', ch=getchar(); while (ch>='' && ch<='');
if (last=='-') num=-num;
return num;
}
inline void putint(int num)
{
char stack[];
register int top=;
if (num<) putchar('-'), num=-num;
if (num==) stack[top=]='';
for ( ;num;num/=) stack[++top]=num%+'';
for ( ;top;top--) putchar(stack[top]);
putchar('\n');
} inline edge * newedge(int index, int point, int dist, edge * next)
{
edge * ret=port_edge++;
ret->index=index; ret->point=point; ret->dist=dist; ret->next=next;
return ret;
}
inline void link(int i, int u, int v, int d)
{
e[u]=newedge(i, v, d, e[u]);
e[v]=newedge(i, u, d, e[v]);
} inline node * newnode()
{
node * ret=port_node++;
ret->c=; ret->l=NULL; ret->r=NULL;
return ret;
}
node * build(int l, int r)
{
node * t=newnode(); if (l==r)
return t; int m=(l+r)>>;
t->l=build(l, m);
t->r=build(m+, r);
t->c=max(t->l->c, t->r->c); return t;
}
void update(node * t, int l, int r, int k, int v)
{
if (l==r)
{
t->c=v;
return ;
} int m=(l+r)>>;
if (k<=m) update(t->l, l, m, k, v);
else update(t->r, m+, r, k, v);
t->c=max(t->l->c, t->r->c);
}
int query(node * t, int l, int r, int ql, int qr)
{
if (l==ql && r==qr)
return t->c; int m=(l+r)>>;
if (qr<=m) return query(t->l, l, m, ql, qr);
else if (ql>m) return query(t->r, m+, r, ql, qr);
else return max(query(t->l, l, m, ql, m), query(t->r, m+, r, m+, qr));
} void dfs(int u)
{
s[u]=;
for (edge * i=e[u];i;i=i->next) if (f[i->point]==-)
{
a[i->point]=i->dist; k[i->index]=i->point;
f[i->point]=u; d[i->point]=d[u]+;
dfs(i->point);
if (s[i->point]>s[son[u]])
son[u]=i->point;
}
}
void divide(int u, int top_u)
{
idx[u]=++num; top[u]=top_u;
if (son[u]) divide(son[u], top_u);
for (edge * i=e[u];i;i=i->next) if (!idx[i->point])
divide(i->point, i->point);
}
inline int query(int u, int v)
{
int ret=; while (top[u]!=top[v])
{
if (d[top[u]]<d[top[v]]) swap(u, v);
ret=max(ret, query(t, , n, idx[top[u]], idx[u]));
u=f[top[u]];
}
if (u==v) return ret; if (d[u]>d[v]) swap(u, v);
ret=max(ret, query(t, , n, idx[u]+, idx[v])); return ret;
} inline void clear()
{
memset(a, , sizeof(a));
memset(k, , sizeof(k));
port_edge=memory_edge; port_node=memory_node;
memset(e, , sizeof(e));
memset(s, , sizeof(s));
memset(f, 0xFF, sizeof(f)); f[]=;
memset(d, , sizeof(d));
num=;
memset(idx, , sizeof(idx));
memset(son, , sizeof(son));
memset(top, , sizeof(top));
}

QTREE

QTREE2: 因为没有修改操作,机智地用了倍增,在 spoj 上貌似挺快的……

 #include <cstdio>
#include <cstring>
const int sizeOfPoint=;
const int sizeOfEdge=; inline void swap(int & , int & );
inline int lg(int);
inline int lowbit(int);
inline char getch();
inline int getint();
inline void putint(int); struct edge {int point, dist; edge * next;};
edge memory[sizeOfEdge], * port=memory;
inline edge * newedge(int, int, edge * );
inline void link(int, int, int); int c, n;
edge * e[sizeOfPoint];
int a[sizeOfPoint], s[sizeOfPoint];
int f[][sizeOfPoint], d[sizeOfPoint];
inline void clear();
void dfs(int);
inline int anc(int, int);
inline int lca(int, int); int main()
{
for (c=getint();c;c--)
{
clear(); n=getint();
for (int i=;i<n;i++)
{
int u=getint(), v=getint(), d=getint();
link(u, v, d);
}
dfs(); while (true)
{
char ch=getch();
if (ch=='O') break;
else if (ch=='I')
{
int u=getint(), v=getint(), l=lca(u, v); putint(s[u]+s[v]-(s[l]<<));
}
else
{
int u=getint(), v=getint(), k=getint(), l=lca(u, v), s=(d[u]-d[l])+(d[v]-d[l])+; if (d[u]-d[l]>=k)
putint(anc(u, k-));
else
putint(anc(v, s-k));
}
}
} return ;
} inline void swap(int & x, int & y)
{
int t=x; x=y; y=t;
}
inline int lg(int x)
{
return x?-__builtin_clz(x):;
}
inline int lowbit(int x)
{
return x & -x;
}
inline char getch()
{
register char ch;
do ch=getchar(); while (ch!='D' && ch!='K');
if (ch=='D') ch=getchar();
return ch;
}
inline int getint()
{
register int num=;
register char ch=, last;
do last=ch, ch=getchar(); while (ch<'' || ch>'');
do num=num*+ch-'', ch=getchar(); while (ch>='' && ch<='');
if (last=='-') num=-num;
return num;
}
inline void putint(int num)
{
char stack[];
register int top=;
if (num==) stack[top=]='';
if (num<) putchar('-'), num=-num;
for ( ;num;num/=) stack[++top]=num%+'';
for ( ;top;top--) putchar(stack[top]);
putchar('\n');
} inline edge * newedge(int point, int dist, edge * next)
{
edge * ret=port++;
ret->point=point; ret->dist=dist; ret->next=next;
return ret;
}
inline void link(int u, int v, int d)
{
e[u]=newedge(v, d, e[u]);
e[v]=newedge(u, d, e[v]);
} inline void clear()
{
port=memory;
memset(e, , sizeof(e));
memset(f, , sizeof(f));
memset(d, 0xFF, sizeof(d)); d[]=;
memset(a, , sizeof(a));
memset(s, , sizeof(s));
}
void dfs(int u)
{
if (d[u]>)
{
int _lim=lg(d[u]);
for (int i=;i<=_lim;i++)
f[i][u]=f[i-][f[i-][u]];
} for (edge * i=e[u];i;i=i->next) if (d[i->point]==-)
{
f[][i->point]=u;
d[i->point]=d[u]+;
a[i->point]=i->dist;
s[i->point]=s[u]+i->dist;
dfs(i->point);
}
}
inline int anc(int u, int s)
{
for ( ;s;s-=lowbit(s))
u=f[__builtin_ctz(s)][u];
return u;
}
inline int lca(int u, int v)
{
if (d[u]<d[v]) swap(u, v);
u=anc(u, d[u]-d[v]);
if (u==v) return u; for (int i=;i>=;i--)
if (f[i][u]!=f[i][v])
u=f[i][u],
v=f[i][v]; return f[][u];
}

QTREE2

QTREE4:

 #include <cstdio>
#include <cstring>
#include <algorithm>
const int sizeOfPoint=;
const int sizeOfEdge=;
const int sizeOfSeg=; inline int lg(int);
inline int rev(int);
inline int getint();
inline void putint(int); struct edge
{
int point;
edge * next;
};
edge memoryOfEdge[sizeOfEdge], * portOfEdge=memoryOfEdge;
inline edge * newedge(int, edge * );
inline void link(int, int); struct seg
{
bool b;
int f;
seg * l, * r;
inline seg();
inline void pushdown();
inline void maintain();
};
seg * null=new seg();
seg memoryOfSeg[sizeOfSeg], * portOfSeg=memoryOfSeg;
inline void swap(seg *& , seg *& );
seg * newseg(seg * =null);
seg * insert(seg * , int, int);
inline int query(seg * ); int n, m;
bool c[sizeOfPoint];
int f[sizeOfPoint];
int sg[sizeOfPoint], s[sizeOfPoint];
int dp[sizeOfPoint];
int tot, ans[sizeOfPoint];
edge * e[sizeOfPoint];
seg * t[sizeOfPoint];
inline void bfs(); int main()
{
n=getint(); m=lg(n);
for (int i=;i<=n;i++)
c[i]=getint();
for (int i=;i<n;i++)
{
int u=getint(), v=getint();
link(u, v);
}
bfs(); if (!tot) ans[tot++]=-;
std::sort(ans, ans+tot);
for (int i=;i<tot;i++)
putint(ans[i]); return ;
} inline int lg(int x)
{
return -__builtin_clz(x);
}
inline int rev(int x)
{
int ret=;
for (int i=;i<m;i++)
{
ret=(ret<<)|(x&);
x>>=;
}
return ret;
}
inline int getint()
{
register int num=;
register char ch;
do ch=getchar(); while (ch<'' || ch>'');
do num=num*+ch-'', ch=getchar(); while (ch>='' && ch<='');
return num;
}
inline void putint(int num)
{
char stack[];
register int top=;
if (num==) stack[top=]='';
if (num<) putchar('-'), num=-num;
for ( ;num;num/=) stack[++top]=num%+'';
for ( ;top;top--) putchar(stack[top]);
putchar('\n');
} inline edge * newedge(int point, edge * next)
{
edge * ret=portOfEdge++;
ret->point=point; ret->next=next;
return ret;
}
inline void link(int u, int v)
{
e[u]=newedge(v, e[u]);
e[v]=newedge(u, e[v]);
} inline seg::seg()
{
b=false;
f=;
l=r=this;
}
inline void seg::pushdown()
{
if (f)
{
if (f&)
{
swap(l, r);
l->f^=f>>, r->f^=f>>;
}
f=;
}
}
inline void seg::maintain()
{
b=l->b&r->b;
}
inline void swap(seg *& a, seg *& b)
{
seg * t=a; a=b; b=t;
}
inline seg * newseg(seg * t)
{
seg * newt=portOfSeg++;
*newt=*t;
if (t==null) newt->b=false, newt->f=;
return newt;
}
seg * insert(seg * t, int k, int d)
{
t=newseg(t);
if (d==) return t->b=true, t;
t->pushdown();
if (k&) t->r=insert(t->r, k>>, d-);
else t->l=insert(t->l, k>>, d-);
t->maintain();
return t;
}
seg * merge(seg * a, seg * b)
{
if (a==null || b->b) return b;
if (b==null || a->b) return a;
a->pushdown(), b->pushdown();
seg * t=newseg();
t->l=merge(a->l, b->l);
t->r=merge(a->r, b->r);
t->maintain();
return t;
}
inline int query(seg * t)
{
int ret=;
for (int i=;i<m;i++)
{
t->pushdown();
if (t->l->b)
{
ret=ret<<|;
t=t->r;
}
else
{
ret=ret<<;
t=t->l;
}
}
return ret;
} inline void bfs()
{
static int q[sizeOfPoint];
int l=, r=;
memset(f, 0xFF, sizeof(f)); f[]=;
for (q[r++]=;l<r;l++)
{
int u=q[l];
for (edge * i=e[u];i;i=i->next) if (f[i->point]==-)
{
f[i->point]=u;
q[r++]=i->point;
}
}
for (int h=r-;h>=;h--)
{
int u=q[h];
t[u]=newseg();
for (edge * i=e[u];i;i=i->next) if (f[i->point]==u)
s[u]^=sg[i->point];
for (edge * i=e[u];i;i=i->next) if (f[i->point]==u)
{
t[i->point]->f^=rev(s[u]^sg[i->point]);
t[u]=merge(t[u], t[i->point]);
}
if (!c[u])
t[u]=insert(t[u], rev(s[u]), m);
sg[u]=query(t[u]);
}
for (int h=;h<r;h++)
{
int u=q[h];
if (!c[u] && dp[u]==s[u]) ans[tot++]=u;
for (edge * i=e[u];i;i=i->next) if (f[i->point]==u)
dp[i->point]=dp[u]^s[u]^sg[i->point];
}
}
 #include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
typedef std::priority_queue<struct pair, std::vector<struct pair>, std::greater<struct pair> > heap;
const int sizeOfPoint=;
const int sizeOfEdge=;
const int sizeOfSeg=; inline int min(int, int);
inline int getint();
inline void putint(int); struct edge
{
int point;
edge * next;
};
edge memoryOfEdge[sizeOfEdge], * portOfEdge=memoryOfEdge;
inline edge * newedge(int, edge * );
inline void link(int, int); struct pair
{
int w, u, t;
inline pair(int, int, int);
};
inline bool operator > (pair, pair); struct node
{
int lmin, rmin, sum;
inline node(int=, int=, int=);
};
inline node merge(node, node); struct seg
{
node d;
seg * l, * r;
inline void maintain();
};
seg memoryOfSeg[sizeOfSeg], * portOfSeg=memoryOfSeg;
inline seg * newseg();
seg * build(int, int);
void update(seg * , int, int, int);
node query(seg * , int, int, int, int); int n, m;
int l[sizeOfPoint], r[sizeOfPoint], b[sizeOfPoint];
bool c[sizeOfPoint];
edge * e[sizeOfPoint];
int d[sizeOfPoint], s[sizeOfPoint], f[sizeOfPoint];
int tmp, idx[sizeOfPoint], son[sizeOfPoint], top[sizeOfPoint];
heap h[sizeOfPoint];
int w[sizeOfPoint];
inline void dfs();
inline void getw(int); int main()
{
n=getint();
for (int i=;i<=n;i++)
{
int u=getint(), v=getint();
link(u, v);
}
dfs(); return ;
} inline int min(int x, int y)
{
return x<y?x:y;
}
inline int getint()
{
register int num=;
register char ch;
do ch=getchar(); while (ch<'' || ch>'');
do num=num*+ch-'', ch=getchar(); while (ch>='' && ch<='');
return num;
}
inline void putint(int num)
{
char stack[];
register int top=;
if (num==) stack[top=]='';
if (num<) putchar('-'), num=-num;
for ( ;num;num/=) stack[++top]=num%+'';
for ( ;top;top--) putchar(stack[top]);
putchar('\n');
} inline edge * newedge(int point, edge * next)
{
edge * ret=portOfEdge++;
ret->point=point; ret->next=next;
return ret;
}
inline void link(int u, int v)
{
e[u]=newedge(v, e[u]);
e[v]=newedge(u, e[v]);
} inline pair::pair(int _w, int _u, int _t)
{
w=_w; u=_u; t=_t;
}
inline bool operator > (pair a, pair b)
{
return a.w>b.w;
} inline node::node(int _lmin, int _rmin, int _sum)
{
lmin=_lmin; rmin=_rmin; sum=_sum;
}
inline node merge(node a, node b)
{
node c;
c.lmin=min(a.lmin, a.sum++b.lmin);
c.rmin=min(b.rmin, a.rmin++b.sum);
c.sum=a.sum++b.sum;
return c;
} inline void seg::maintain()
{
d=merge(l->d, r->d);
}
inline seg * newseg()
{
return portOfSeg++;
}
seg * build(int l, int r)
{
seg * t=newseg();
int m=(l+r)>>; if (l==r)
{
t->d.lmin=t->d.rmin=w[m];
t->d.sum=;
}
else
{
t->l=build(l, m);
t->r=build(m+, r);
t->maintain();
} return t;
}
void update(seg * t, int l, int r, int k)
{
int m=(l+r)>>; if (l==r)
t->d.lmin=t->d.rmin=w[m];
else
{
if (k<=m) update(t->l, l, m, k);
else update(t->r, m+, r, k);
t->maintain();
}
}
node query(seg * t, int l, int r, int ql, int qr)
{
if (l==ql && r==qr) return t->d;
int m=(l+r)>>;
if (qr<=m) return query(t->l, l, m, ql, qr);
else if (ql>m) return query(t->r, m+, r, ql, qr);
else return merge(query(t->l, l, m, ql, m), query(t->r, m+, r, m+, qr));
} inline void dfs()
{
static edge * t[sizeOfPoint];
memmove(t, e, sizeof(e));
}

QTREE5

激!QTREE系列的更多相关文章

  1. QTREE系列题解

    打了快一星期的qtree终于打完了- - (其实还有两题改不出来弃疗了QAQ) orz神AK一星期前就虐完QTREE 避免忘记还是简单写下题解吧0 0 QTREE1 题意: 给出一颗带边权树 一个操作 ...

  2. SPOJ QTREE 系列解题报告

    题目一 : SPOJ 375 Query On a Tree http://www.spoj.com/problems/QTREE/ 给一个树,求a,b路径上最大边权,或者修改a,b边权为t. #in ...

  3. QTREE系列题目总结

    $QTREE$ 就是一套树上数据结构练习题. 这套题貌似来源于 $SPOJ$,我是在 $luogu$ 看到的. $QTREE1$ 题意 一棵 $n$ 个点的带边权树,要求支持 单边改权值 和 询问路径 ...

  4. SPOJ Qtree系列 5/7

    Qtree1 树剖裸题 注意把边权移到深度较深的点上,树剖跳的时候不要将LCA的答案统计上就行了 #include<stdio.h> #include<string.h> #d ...

  5. SPOJ Qtree系列

    Qtree1 将边权变为这条边连接的两个点中深度更深的点的点权,这样就可以变为带修改链上最大点权.直接树链剖分即可. 下面是一份C语言代码 #include<stdio.h> #inclu ...

  6. SPOJ GSS系列

    众所周知的仅次于ynoi的毒瘤数据结构系列.(跟Qtree系列并列?) GSS1: 长度为 $n$ 的序列 $a$,$m$ 个询问,每次询问区间 $[l,r]$ 之间的最大子段和. $1\le n,m ...

  7. 树链剖分X2

    1.ZJOI树的统计 板子题 因为初始化没打改了几个小时 改到双腿软着出的机房(身体素质感人 #include<iostream> #include<cstdio> #incl ...

  8. HBSX2019 游记

    Day -4 训练戳SX2019 3月训练 ZJOI2019 Day1几天前就考了 T1真考了麻将QwQ 九条可怜的毒瘤真的是业界良心 今天中午才起,要开始调整生物钟了 9012HBOIers群里讨论 ...

  9. [题解]luogu P4116 Qtree3

    终于来到了Qtree3, 其实这是Qtree系列中最简单的一道题,并不需要线段树, 只要树链剖分的一点思想就吼了. 对于树链剖分剖出来的每一根重链,在重链上维护一个Set就好了, 每一个Set里存的都 ...

随机推荐

  1. $.getJSON('url',function(data){}) 中回调函数不执行

    $.getJSON('url',function(data){}) 中回调函数不执行 url 中的 json 格式不正确 ,浏览器返回并没有报错 {'湖北':[114.11438,30.849429] ...

  2. Unreal Engine Plugin management

    Be aware to remove any dependencies to any modules related to Editor, or else it will end up with fa ...

  3. Yosemite系统怎么录制 iOS8设备屏幕

    我一年前一直想要的一个功能,发布时很想用.一直没找到 ,很巧的是今天被测试发现了. 感谢CCTV.自己在这里也记录下: 你好!    在 OS X Yosemite  系统中,QuickTime 支持 ...

  4. oc swizzling 真的好用

    Objective-C的hook方案(一):  Method Swizzling 在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写.和借助类别重名方法暴力抢先之外,还有更加灵活 ...

  5. Jqgrid学习API

    JQGrid是一个在jquery基础上做的一个表格控件,以ajax的方式和服务器端通信. JQGrid Demo 是一个在线的演示项目.在这里,可以知道jqgrid可以做什么事情. 下面是转自其他人b ...

  6. spring mvc 获取页面日期格式数据

    1.传递日期参数: 解决办法: 实体类日期属性加 @DateTimeFormat(pattern="yyyy-MM-dd") 注解 beans中加 <mvc:annotati ...

  7. vfp 智能感知拓展应用

    *======================================================================================== * * Versio ...

  8. 关于asp.net的一点小问题有谁帮忙解答一下?

    public IList<Category> Categories { get; set; }        protected void Page_Load(object sender, ...

  9. update the UI property cross thread

    this.Invoke((MethodInvoker)delegate { txtResult.Text = sbd.ToString(); // runs on UI thread });

  10. IOS UI多线程 NSThread 下载并显示图片到UIImageView

    效果图 @property (weak,nonatomic)IBOutletUILabel *downLabelInfo; @property (weak,nonatomic)IBOutletUIIm ...