激!QTREE系列
我现在才开始刷 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系列的更多相关文章
- QTREE系列题解
打了快一星期的qtree终于打完了- - (其实还有两题改不出来弃疗了QAQ) orz神AK一星期前就虐完QTREE 避免忘记还是简单写下题解吧0 0 QTREE1 题意: 给出一颗带边权树 一个操作 ...
- SPOJ QTREE 系列解题报告
题目一 : SPOJ 375 Query On a Tree http://www.spoj.com/problems/QTREE/ 给一个树,求a,b路径上最大边权,或者修改a,b边权为t. #in ...
- QTREE系列题目总结
$QTREE$ 就是一套树上数据结构练习题. 这套题貌似来源于 $SPOJ$,我是在 $luogu$ 看到的. $QTREE1$ 题意 一棵 $n$ 个点的带边权树,要求支持 单边改权值 和 询问路径 ...
- SPOJ Qtree系列 5/7
Qtree1 树剖裸题 注意把边权移到深度较深的点上,树剖跳的时候不要将LCA的答案统计上就行了 #include<stdio.h> #include<string.h> #d ...
- SPOJ Qtree系列
Qtree1 将边权变为这条边连接的两个点中深度更深的点的点权,这样就可以变为带修改链上最大点权.直接树链剖分即可. 下面是一份C语言代码 #include<stdio.h> #inclu ...
- SPOJ GSS系列
众所周知的仅次于ynoi的毒瘤数据结构系列.(跟Qtree系列并列?) GSS1: 长度为 $n$ 的序列 $a$,$m$ 个询问,每次询问区间 $[l,r]$ 之间的最大子段和. $1\le n,m ...
- 树链剖分X2
1.ZJOI树的统计 板子题 因为初始化没打改了几个小时 改到双腿软着出的机房(身体素质感人 #include<iostream> #include<cstdio> #incl ...
- HBSX2019 游记
Day -4 训练戳SX2019 3月训练 ZJOI2019 Day1几天前就考了 T1真考了麻将QwQ 九条可怜的毒瘤真的是业界良心 今天中午才起,要开始调整生物钟了 9012HBOIers群里讨论 ...
- [题解]luogu P4116 Qtree3
终于来到了Qtree3, 其实这是Qtree系列中最简单的一道题,并不需要线段树, 只要树链剖分的一点思想就吼了. 对于树链剖分剖出来的每一根重链,在重链上维护一个Set就好了, 每一个Set里存的都 ...
随机推荐
- JAVA 内部类 泛型 实现堆栈
堆栈类: package c15; public class LinkedStack<T> { private static class Node<T> { T item ; ...
- 软件分析(Mobile Apps )--百词斩
1) 此类软件是什么时候开始出现的, 这些软件是怎么说服你(陌生人)成为他们的用户的? 他们的目标都是盈利么? 他们的目标都是赚取用户的现金么?还是别的? 2) 你个人第一次用此类软件是什么时候,你当 ...
- break into Ubuntu System
This morning, I got a spare machine from of of the labmates. The OS is ubuntu 12.04. I could not log ...
- Amoeba for MySQL读写分离配置
一. 安装和运行Amoeba 1. Amoeba for MySQL 架构: 2. 验证Java的安装Amoeba框架是基于Java SE1.5开发的,建议使用Java SE1.5以上的版本 ...
- iOS开发:正则表达式
语法/字符说明表 值表达 . 匹配除换行符外的任意字符 \w 匹配字母或者数字的字符 \W 匹配任意不是字母或数字的字符 \s 匹配任意的空白符(空格.制表符.换行符) \S ...
- 华为手机调试显示log日志
华为手机默认状态手机log为关闭状态,所以看不到详细错误信息. 手机拨号*#*#2846579#*#*,进入projectmenu--后台设置--LOG设置--LOG开关--打开 勾选AP日志 C ...
- css3弹性盒子温习
弹性盒子由弹性容器(Flex container)和弹性子元素(Flex item)组成. 弹性容器通过设置 display 属性的值为 flex 或 inline-flex将其定义为弹性容器. 弹性 ...
- Java学习1 - java 历史
Sun的Java语言开发小组成立于1991年,其目的是开拓消费类电子产品市场,例如:交互式电视,烤面包箱等.Sun内部人员把这个项目称为 Green,那时World Wide Web还在图纸上呢.该小 ...
- iOS保存cookie的方法
SURLRequest*request =[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com/ ...
- 一维码生成 c# winform GUI
最近看到同事小红在做一维码,感觉挺好玩,于是就在网上找了一个例子来玩玩. 下面的代码均为网上的代码,做了一些整理,但是忘记了出处,原作者看到可以提醒我,谢谢. 首先,一维码的相关知识可以先百度一下:h ...