luogu P3565 [POI2014]HOT-Hotels
无脑暴力+O2=AC
题目要统计距离两两相等的三个点的组数,这三个点之间显然有一个点,并且这三个点到这个点的距离都相同.所以枚举中间这个点作为根,然后bfs整棵树,对于每一层,把以根的某个儿子的子树中在这一层点的数量统计出来,那么这样三元组的数量就是在这些点里面选3个点,并且分别来自不同子树的方案,\(f_{i,0/1/2/3}\)即可
详见代码
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
using namespace std;
const int N=5000+10;
il int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
LL ans,f[N][4];
int to[N<<1],nt[N<<1],hd[N],dg[N],tot=1,a[N];
bool v[N];
il void add(int x,int y)
{
++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot,++dg[x];
++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot,++dg[y];
}
int n,m;
int main()
{
n=rd();
for(int i=1;i<n;++i) add(rd(),rd());
for(int i=0;i<=n;++i) f[i][0]=1;
queue<int> id[2],q[2];
for(int i=1;i<=n;++i)
{
memset(v,0,sizeof(v));
v[i]=1;
while(!id[0].empty()) id[0].pop();
while(!id[1].empty()) id[1].pop();
while(!q[0].empty()) q[0].pop();
while(!q[1].empty()) q[1].pop();
m=dg[i];
int nw=1,la=0;
for(int j=hd[i],k=1;j;j=nt[j],++k) id[0].push(k),q[0].push(to[j]);
while(!q[la].empty())
{
memset(a,0,4*(m+1));
while(!q[la].empty())
{
int k=id[la].front(),x=q[la].front();
id[la].pop(),q[la].pop();
++a[k],v[x]=true;
for(int j=hd[x];j;j=nt[j])
{
int y=to[j];
if(!v[y]) id[nw].push(k),q[nw].push(y);
}
}
for(int j=1;j<=m;++j)
{
for(int k=1;k<=3;++k) f[j][k]=f[j-1][k]+f[j-1][k-1]*a[j];
}
ans+=f[m][3];
swap(nw,la);
}
}
printf("%lld\n",ans);
return 0;
}
正解是长链剖分
咕咕咕
其实上面那个dp比较沙雕,可以直接设\(f_{i,j}\)为点\(i\)子树内到\(i\)距离为\(j\)的点个数,\(g_{i,j}\)为点\(i\)子树内,到lca距离为\(d\),且这个lca到\(i\)距离为\(d-j\)的点对个数,然后转移就是
\]
对整棵树长链剖分之后,那么转移时就直接可以继承重儿子的信息,轻儿子直接暴力合并,因为每个点只会在链顶被暴力合并上去,所以复杂度是\(O(n)\)的
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
using namespace std;
const int N=100000+10;
il int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int to[N<<1],nt[N<<1],hd[N],tot=1;
il void add(int x,int y)
{
++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
}
int n,m;
int ff[N],de[N],dpt[N],son[N];
LL *f[N],*g[N],rbq[N<<3],*uc=rbq,ans;
void dfs1(int x)
{
dpt[x]=de[x];
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(y==ff[x]) continue;
ff[y]=x,de[y]=de[x]+1,dfs1(y),dpt[x]=max(dpt[x],dpt[y]);
if(dpt[son[x]]<dpt[y]) son[x]=y;
}
}
void dd(int x)
{
if(son[x]) f[son[x]]=f[x]+1,g[son[x]]=g[x]-1,dd(son[x]);
f[x][0]=1,ans+=g[x][0];
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(y==ff[x]||y==son[x]) continue;
f[y]=uc,uc+=(dpt[y]-de[x]+1)<<1,g[y]=uc,uc+=(dpt[y]-de[x]+1)<<1;
dd(y);
for(int j=0;j<dpt[y]-de[x];++j)
{
if(j) ans+=f[x][j-1]*g[y][j];
ans+=g[x][j+1]*f[y][j];
}
for(int j=0;j<dpt[y]-de[x];++j)
{
g[x][j+1]+=f[x][j+1]*f[y][j];
if(j) g[x][j-1]+=g[y][j];
f[x][j+1]+=f[y][j];
}
}
}
int main()
{
n=rd();
for(int i=1;i<n;++i) add(rd(),rd());
de[1]=1,dfs1(1);
f[1]=uc,uc+=(dpt[1]+1)<<1,g[1]=uc,uc+=(dpt[1]+1)<<1;
dd(1);
printf("%lld\n",ans);
return 0;
}
luogu P3565 [POI2014]HOT-Hotels的更多相关文章
- Luogu P3577 [POI2014]TUR-Tourism
Luogu P3577 [POI2014]TUR-Tourism 题目链接 题目大意:给出一张\(n\)个点,\(m\)条边的无向图,保证任意两点之间没有点数超过\(10\)的简单路径.选择第\(i\ ...
- luogu P3567 [POI2014]KUR-Couriers
二次联通门 : luogu P3567 [POI2014]KUR-Couriers MMP 指针 RE + MLE + WA..... 不得已...向黑恶的数组实力低头 /* 指针 */ #inclu ...
- 主席树||可持久化线段树||BZOJ 3524: [Poi2014]Couriers||BZOJ 2223: [Coci 2009]PATULJCI||Luogu P3567 [POI2014]KUR-Couriers
题目:[POI2014]KUR-Couriers 题解: 要求出现次数大于(R-L+1)/2的数,这样的数最多只有一个.我们对序列做主席树,每个节点记录出现的次数和(sum).(这里忽略版本差值问题) ...
- P3565 [POI2014]HOT-Hotels
题目描述 There are nn towns in Byteotia, connected with only n-1n−1 roads. Each road directly links two ...
- [luogu]P3572 [POI2014]PTA-Little Bird(单调队列)
P3572 [POI2014]PTA-Little Bird 题目描述 In the Byteotian Line Forest there are nn trees in a row. On top ...
- luogu P3576 [POI2014]MRO-Ant colony
传送门 一群蚂蚁能被吃,也就是走到指定边的两端点之一要走到另一端点时有\(k\)只,我们可以从这两端点逆推,记两个值为走到某个点时最后会被吃掉\(k\)只蚂蚁的蚂蚁数量范围,式子下面有,很好理解(雾) ...
- Luogu P3579 [POI2014]PAN-Solar Panels
题目大意: 给出T组询问,每组询问给出四个数a,b,c,d,每次询问满足a<=x<=b,c<=y<=d的gcd(x,y)的最大值 首先可以想到如果存在gcd(x,y)=k,那么 ...
- luogu P3572 [POI2014]PTA-Little Bird |单调队列
从1开始,跳到比当前矮的不消耗体力,否则消耗一点体力,每次询问有一个步伐限制,求每次最少耗费多少体力 #include<cstdio> #include<cstring> #i ...
- luogu P3572 [POI2014]PTA-Little Bird
题目描述 从1开始,跳到比当前矮的不消耗体力,否则消耗一点体力,每次询问有一个步伐限制,求每次最少耗费多少体力 单调队列优化动态规划 #include<cstdio> #include&l ...
随机推荐
- Delphi中的Sender:TObject对象解析
Delphi中的Sender:TObject对象解析 procedure TForm1.Button1Click(Sender: TObject); begin end; 解析:Procedure是过 ...
- js條件結構和循環結構
條件結構: if(語句1) if(語句1)else(語句2) if(語句1)elseif(語句2)else(語句3) switch結構: switch() { case 1: break: case ...
- python之多线程举例
# 多线程举例 from threading import Thread from threading import current_thread class messager(Thread): de ...
- SQL连接:内连接、外连接、交叉连接。
SQL连接可以分为内连接.外连接.交叉连接. 数据库数据: book表 stu表 1.内连接 ...
- codeforces369A
Valera and Plates CodeForces - 369A Valera is a lazy student. He has m clean bowls and k clean plate ...
- 自定义缓存设计(static缓存数据)
设计题 编程过程中,为了解决缓存数据共享的问题,常常会使用static关键字达到脱离具体实例化对象,在整个java进程生命周期内共享数据的目的.请编写一个类,类名为MapCache,拥有但不局限于以下 ...
- tmux的使用
tmux的使用 1: tmux的介绍 tmux是一个优秀的终端多路复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授权.使用它最直观的好处就是,通过一个终端登录远程主机并 ...
- mysql 免安装版 启动服务马上关闭
在my.ini 加入这一句 1.直接在后面加上一下的参数 [mysqld] port=3306 basedir=D:\mysql-5.7.17-win32 datadir=D:\mysql-5.7.1 ...
- wireshark配合jmeter测试webservice接口
1.首先,获取本地和接口的ip,以便设置过滤 2.wireshark设置过滤 ip.dst==192.168.0.101 and ip.src==61.147.124.120 and http 3.执 ...
- luogu1073 最优贸易 (tarjan+dp)
tarjan缩点,然后按照拓扑序,做1号点能到达的点的答案具体做法是对每个点记一个min[i],max[i],vis[i]和ans[i]做拓扑序的时候,假设在从u点开始做,有边u到v,如果vis[u] ...