总结

由于受中秋节影响,没能在比赛时间内切掉\(T3\)

思维难度\(T1<T2<T3\),代码难度\(T1>T2>T3\)

P5557 旅行

显然跳到环上去后就可以直接模了,所以一遍遍历找到每个点是否在环上

如在环上求出环上\(len\),如不在求出到环还需走的长度\(Len\),预处理出每个点走\(2^i\)的位置

\(t1^t2\)由于过大不能直接求,在快速幂的同时求出判断大于\(Len\)

  • 大于先记录,另走到环上,最终落在环上的位置距离环头为\(x\equiv t1^t2-Len(mod~len)\)

  • 小于说明该数并不大,直接倍增走

#include<bits/stdc++.h>
typedef long long LL;
const LL maxn=400009;
inline LL Read(){
LL x(0),f(1); char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<3ll)+(x<<1ll)+c-'0'; c=getchar();
}return x*f;
}
LL n,m,top,tim;
LL a[maxn],f[maxn][21],seed[21],visit[maxn],len[maxn],sta[maxn],dep[maxn],Len[maxn],dfn[maxn];
inline LL Pow(LL base,LL b,LL mod){
LL ret(1);
while(b){
if(b&1) ret=1ll*ret*base%mod;
base=1ll*base*base%mod; b>>=1;
}return ret;
}
void Dfs1(LL u){
sta[++top]=u; dfn[u]=++tim;
LL v(a[u]);
visit[u]=1;
if(visit[v] && !Len[v]){
len[u]=dep[u]-dep[v]+1;
LL now;
do{
now=sta[top--]; len[now]=len[u]; visit[now]=false;
}while(now!=v);
return;
}
dep[v]=dep[u]+1;
if(!dfn[v]) Dfs1(v);
if(!len[u]){
Len[u]=Len[v]+1;
}
}
int main(){
n=Read();
for(LL i=1;i<=n;++i) a[i]=Read(),f[i][0]=a[i];
for(LL i=1;i<=n;++i){
if(!dfn[i]) dep[i]=0,Dfs1(i);
}
for(LL j=1;j<=20;++j)
for(LL i=1;i<=n;++i)
f[i][j]=f[f[i][j-1]][j-1];
seed[0]=1;
for(LL i=1;i<=20;++i) seed[i]=seed[i-1]*2;
m=Read();
while(m--){
LL s(Read()),t1(Read()),t2(Read()),now1(s);
if(Len[s]){
LL base(t1),b(t2),R(1),flag(0),tmp(Len[s]);
while(b){
if(b&1){
R=R*base;
if(R>tmp){
flag=true; break;
}
} base=base*base;
if(b!=1){
if(base>tmp){
flag=1; break;
}
}
b>>=1;
}
if(!flag){
tmp=R;
for(LL i=20;i>=0;--i){
if(tmp>=seed[i]){
tmp-=seed[i]; now1=f[now1][i];
}
if(!tmp){
printf("%lld\n",now1); break;
}
}
continue;
}else{
for(LL i=20;i>=0;--i){
if(tmp>=seed[i]){
tmp-=seed[i]; now1=f[now1][i];
}
}
}
}
LL ret,now(now1);
ret=(Pow(t1,t2,len[now])-Len[s]%len[now]+len[now])%len[now];、
if(!ret){
printf("%lld\n",now); continue;
}
for(LL j=20;j>=0;--j){
if(ret>=seed[j])
ret-=seed[j],now=f[now][j];
if(!ret){
printf("%lld\n",now); break;
}
}
}
return 0;
}

P5558 心上秋

发现边颜色恒为正且小于\(5\),求得\(inc_{i,j,c1,c2},low_{i,j,c1,c2}\)分别为\(i\)到\(i\)的\(2^j\)级祖先,子序列首\(c1\)尾\(c2\),单调不减/单调不增,的最长长度

对于每个查询,对\(x-lca\)把\(inc\)合起来,对\(y-lca\)把\(low\)合起来,然后在\(dp\)一遍即可

\(O(5^4(n+q)logn)\),由于转移的时候\(5^4\)卡不满,所以跑得不慢

#include<bits/stdc++.h>
typedef int LL;
const LL maxn=30009;
inline LL Read(){
LL x(0),f(1); char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<3ll)+(x<<1ll)+c-'0'; c=getchar();
}return x*f;
}
struct node{
LL to,nxt,w;
}dis[maxn<<1];
LL n,m,num;
LL head[maxn],f1[6][6],f2[6][6],inc[maxn][16][6][6],low[maxn][16][6][6],F[maxn][16],dep[maxn],tmp[6][6];
inline void Add(LL u,LL v,LL w){
dis[++num]=(node){v,head[u],w}; head[u]=num;
}
void Dfs(LL u,LL f,LL c){
if(u!=1){
inc[u][0][c][c]=1; low[u][0][c][c]=1;
F[u][0]=f; for(LL i=1;i<=15;++i) F[u][i]=F[F[u][i-1]][i-1];
for(LL i=1;i<=15;++i){
for(LL j=1;j<=5;++j)
for(LL k=j;k<=5;++k)
for(LL jj=j;jj<=k;++jj)
for(LL kk=jj;kk<=k;++kk)
inc[u][i][j][k]=std::max(inc[u][i][j][k],inc[u][i-1][j][jj]+inc[F[u][i-1]][i-1][kk][k]);
}
for(LL i=1;i<=15;++i){
for(LL j=1;j<=5;++j)
for(LL k=1;k<=j;++k)
for(LL jj=k;jj<=j;++jj)
for(LL kk=k;kk<=jj;++kk)
low[u][i][j][k]=std::max(low[u][i][j][k],low[u][i-1][j][jj]+low[F[u][i-1]][i-1][kk][k]);
}
}
for(LL i=head[u];i;i=dis[i].nxt){
LL v(dis[i].to);
if(v==f) continue;
dep[v]=dep[u]+1;
Dfs(v,u,dis[i].w);
}
}
inline LL Lca(LL u,LL v){
if(dep[u]<dep[v]) std::swap(u,v);
for(LL i=15;i>=0;--i)
if(dep[F[u][i]]>=dep[v]) u=F[u][i];
if(u==v) return u;
for(LL i=15;i>=0;--i)
if(F[u][i]!=F[v][i]) u=F[u][i],v=F[v][i];
return F[u][0];
}
inline void Solve1(LL u,LL f){
memset(f1,0,sizeof(f1));
LL ret(dep[u]-dep[f]);
for(LL i=15;i>=0;--i){
if((ret&(1<<i))==(1<<i)){
memcpy(tmp,f1,sizeof(f1));
memset(f1,0,sizeof(f1));
for(LL j=1;j<=5;++j)
for(LL k=j;k<=5;++k)
for(LL jj=j;jj<=k;++jj)
for(LL kk=jj;kk<=k;++kk)
f1[j][k]=std::max(f1[j][k],tmp[j][jj]+inc[u][i][kk][k]);
u=F[u][i];
}
}
}
inline void Solve2(LL u,LL f){
memset(f2,0,sizeof(f2));
LL ret(dep[u]-dep[f]);
for(LL i=15;i>=0;--i){
if((ret&(1<<i))==(1<<i)){
memcpy(tmp,f2,sizeof(f2));
memset(f2,0,sizeof(f2));
for(LL j=1;j<=5;++j)
for(LL k=1;k<=j;++k)
for(LL jj=k;jj<=j;++jj)
for(LL kk=k;kk<=jj;++kk)
f2[j][k]=std::max(f2[j][k],tmp[j][jj]+low[u][i][kk][k]);
u=F[u][i];
}
}
}
int main(){
n=Read();
for(LL i=1;i<n;++i){
LL u(Read()),v(Read()),w(Read());
Add(u,v,w); Add(v,u,w);
}
Dfs(1,0,0);
m=Read();
while(m--){
LL u(Read()),v(Read());
LL lca(Lca(u,v));
Solve1(u,lca); Solve2(v,lca);
LL ans(0);
for(LL i=1;i<=5;++i)
for(LL j=i;j<=5;++j)
for(LL ii=i;ii<=j;++ii)
for(LL jj=ii;jj<=j;++jj)
ans=std::max(ans,f1[i][ii]+f2[j][jj]);
printf("%d\n",ans);
}
return 0;
}

P5559 失昼城的守星使

题意:有边权树,初始点权均为\(1\),操作可对某个点点权取反/给出一个点对\((u,v)\)求该链每个正点到其链最短距离之和

每个黑点到根的路径全部加一遍边权,显然可以用树链剖分维护,设\(Dis(x,y)\)为\(x\)到\(y\)的边权和

\(S\)为每个黑点到根的距离和,\(tot\)为黑点个数,\(dep_x\)为\(x\)到根的距离

设\(x=Lca(u,v)\),答案为\(S+tot*dep_lca-2*Dis(1,x)\),这部分为\(x\)外的贡献剩下的为"下面"的到\(x\)的距离和

再减去\(Dis(x,y)\)则为最终答案

CTYZ的树论赛(P5557 旅行/P5558 心上秋/P5559 失昼城的守星使)的更多相关文章

  1. luogu P5558 心上秋

    LINK:心上秋 唐多令 宋 吴文英 何处合成愁.离人心上秋.纵芭蕉,不雨也飕飕.都道晚凉天气好,有明月,怕登楼. 年事梦中休.花空烟水流.燕辞归,客尚淹留.垂柳不萦裙带住.漫长是,系行舟. 心上秋 ...

  2. csp-s模拟测试55(9.29)联「线段树」·赛「??」题「神仙DP」

    T1 联 考试两个小时终于调过了,话说一个傻逼错最后还是静态查出错的..... 大概维护两个懒标记,一个区间覆盖,一个区间异或,然后保证每个区间只会存在一种懒标记. 然后维护区间0的个数,查询时查询那 ...

  3. 【块状树】【树链剖分】【线段树】bzoj3531 [Sdoi2014]旅行

    离线后以宗教为第一关键字,操作时间为第二关键字排序. <法一>块状树,线下ac,线上tle…… #include<cstdio> #include<cmath> # ...

  4. POJ 1985.Cow Marathon-树的直径-树的直径模板(BFS、DFS(vector存图)、DFS(前向星存图))

    Cow Marathon Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 7536   Accepted: 3559 Case ...

  5. 树剖LCA讲解

    LCA的类型多种多样,只说我知道的,就有倍增求LCA,tarjin求LCA和树链剖分求LCA,当然,也还有很多其他的方法. 其中最常用,速度最快的莫过于树链剖分的LCA了. 树链剖分,首先字面理解一下 ...

  6. 【转】B-树和B+树的应用:数据搜索和数据库索引

    B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树: ⑴树中每个结点至多有m 棵子树: ⑵若根结点不是叶子 ...

  7. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  8. hdu1890 伸展树(区间反转)

    对于大神来说这题是水题.我搞这题花了快2天. 伸展树的优点有什么,就是树不管你怎么旋转序列是不会改变得,并且你要使区间反转,只要把第k大的点转到根结点,那么它的左子树就是要交换的区间[l,r),然后交 ...

  9. B-树和B+树的应用:数据搜索和数据库索引

    B-树和B+树的应用:数据搜索和数据库索引  B-树 1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树:⑴树中每 ...

随机推荐

  1. 【图解】cpu,内存,硬盘,指令的关系

    1 程序员用高级语言编写程序. 2 经过编译 链接等形成机器语言的EXE文件. 3 EXE文件保持在磁盘的某个或多个扇区内 4 程序运行是在内存中生成EXE的副本 5 将指令读入cpu的寄存器 6 由 ...

  2. 修改Excel脚本

    批量修改Excel TODO: 批量修改Excel 功能: 将图片防止在本地,读取excel数据,拆分数据之后根本地照片名称对比,然后上传服务器,创建新得excel. #!/usr/bin/pytho ...

  3. 【洛谷 P3346】 [ZJOI2015]诸神眷顾的幻想乡(后缀自动机)

    题目链接 广义sam+不同子串个数.. 找到所有入度为\(0\)的点开始\(dfs\),建出广义sam. 然后就是不同子串个数了 #include <cstdio> #include &l ...

  4. 【洛谷 P5357】 【模板】AC自动机(二次加强版)(AC自动机,差分)

    每次匹配都不停跳fail显然太慢了,于是在每个节点和fail指向的点连一条边,构成一棵树,在这棵树上差分一下就好了. AC自动机 就这个算法而言其实没用想象中那么难. #include <cst ...

  5. 【转载】 C#使用string.IsNullOrWhiteSpace方法判断字符串是否为非空字符

    在C#编程过程中,很多时候需要判断传入过来的字符串是否为Null或者空字符或者空白字符,此时就可以使用到string.IsNullOrWhiteSpace方法来判断,如果字符串为null或者空字符Em ...

  6. webapp之登录页面当input获得焦点时,顶部版权文本被顶上去 的解决方法

    如上图,顶部版权是用绝对定位写的,被顶上去了,解决方法是判断屏幕大小,改变footer的定位方式: <script> var oHeight = $(document).height(); ...

  7. 5G能带来什么改变-从鸿蒙OS说起

    背景 从5G投票事件开始,开始关注5G.许多文章都说到5G的特点有速度快.时延低,其中,时延低是最重要的特点.然而,时延低能给社会带来什么改变呢? 2G是短信的时代,3G促成了语音视频,4G促成了短视 ...

  8. 在SAP Hybris commerce Storefront里购物下单

    操作过程和大家平时在网上购物没有太大差别. 选中一款心仪的产品,点击Add to cart加到购物车里: 点击Check out结帐: 生成一个购物车ID: 维护发货地址: 维护发货方式: 点击Pla ...

  9. [LeetCode] 25. K 个一组翻转链表 ☆☆☆☆☆(链表)

    https://leetcode-cn.com/problems/reverse-nodes-in-k-group/solution/javadi-gui-fang-fa-100-by-chadriy ...

  10. 关于MQ的几件小事:消息队列的用途、优缺点、技术选型

    原文:https://www.cnblogs.com/jack1995/p/10908789.html 1.为什么使用消息队列? (1)解耦:可以在多个系统之间进行解耦,将原本通过网络之间的调用的方式 ...