A:
题意:一张无向图,每次询问ki,vi计算从ki出发,只走边权大于vi的边,能到几条边。
思路:离线操作,先计算vi大的询问,询问前加上边权大于vi的边,用并查集计算。
B:
题意:一棵树,叶子节点是出口,牛从K点出发,在某些出口有村民抓牛,村民和牛的速度都是1,村民合理行动的情况下至少多少个村民能抓住牛。
思路:把K当做树根,每次牛一定往下走,考虑到一个点时,如果牛到他的距离比某一个叶子节点到他的距离长或相等,那么以这个点为根的子树只用一个人就够了,否则递归。
C:
题意:一横排n个格,有m种颜色的章,每个长度都是k,每个章可以用多次,涂色可以覆盖,不能涂到外面去,涂完色要求每个格都有色,问有最终有多少种图案。
思路:最后一个章一定让某处连续k个数有一样的颜色,其他的地方颜色随意。所以就是求长度为n的至少k个连续的格子颜色相同的方案数。可以通过求不存在连续k个格子颜色相同的个数来算。这样dp[i]表示长度是i的方案数,dp[i]可以由dp[i-k+1]到dp[i-1]计算出,每项都乘m-1,表示从这个长度往后都是一种与它最后一个格不同的颜色,则
d
p
[
i
]
=
(
m
−
1
)
∑
j
=
i
−
k
+
1
i
−
1
d
p
[
j
]
dp[i]=(m-1)\sum_{j=i-k+1}^{i-1}dp[j]
dp[i]=(m−1)∑j=i−k+1i−1dp[j],可以用前缀和优化做出。题解中的技巧:用s[i]表示前i项和,
s
[
i
]
−
s
[
i
−
1
]
=
(
m
−
1
)
(
d
p
[
i
−
1
]
−
d
p
[
i
−
k
]
)
s[i]-s[i-1]=(m-1)(dp[i-1]-dp[i-k])
s[i]−s[i−1]=(m−1)(dp[i−1]−dp[i−k]),整理得
s
[
i
]
=
m
∗
s
[
i
−
1
]
−
(
m
−
1
)
∗
s
[
i
−
k
]
s[i]=m*s[i-1]-(m-1)*s[i-k]
s[i]=m∗s[i−1]−(m−1)∗s[i−k]然后计算s数组,避免前缀和优化。
A:
#include<cstdio>
#include<string>
#include<cstring>
#include<utility>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#include<algorithm>
#include<vector>
#include<iostream>
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define inf 0x7fffffff
#define minn(x,y) x=min(x,y)
#define maxx(x,y) x=max(x,y)
using namespace std;
pair<int,pii> a[100010];
pair<pii,int> r[100010];
int fa[100010],c[100010];
int find(int x)
{
if(fa[x]==x)
{
return x;
}
return fa[x]=find(fa[x]);
}
int add(pair<int,pii> x)
{
int fx=find(x.se.fi);
int y=find(x.se.se);
c[fx]+=c[y];
fa[y]=fx;
}
int ans[100010];
int main()
{
int i,j,k,n,m,x,y,z,q;
freopen("mootube.in","r",stdin);
freopen("mootube.out","w",stdout);
scanf("%d%d",&n,&q);
for(i=0;i<n-1;i++)
{
scanf("%d%d%d",&x,&y,&z);
a[i]=mp(z,mp(x,y));
}
sort(a,a+n-1);
reverse(a,a+n-1);
for(i=0;i<q;i++)
{
scanf("%d%d",&x,&y);
r[i]=mp(mp(x,y),i);
}
sort(r,r+q);
reverse(r,r+q);
j=0;
for(i=0;i<=n;i++)
{
fa[i]=i;
c[i]=1;
}
for(i=0;i<q;i++)
{
while(a[j].fi>=r[i].first.fi)
{
add(a[j]);
j++;
}
ans[r[i].se]=c[find(r[i].first.se)]-1;
}
for(i=0;i<q;i++)
{
printf("%d\n",ans[i]);
}
}
B:
#include<cstdio>
#include<string>
#include<cstring>
#include<utility>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#include<algorithm>
#include<vector>
#include<iostream>
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define inf 0x7fffffff
#define minn(x,y) x=min(x,y)
#define maxx(x,y) x=max(x,y)
using namespace std;
vector<int> ve[100010];
int d[100010],d1[100010];
int dfs1(int x,int q,int p)
{
d[x]=q;
int i,l=0x7ffffff;
for(i=0;i<ve[x].size();i++)
{
if(ve[x][i]!=p)
{
l=min(l,dfs1(ve[x][i],q+1,x));
}
}
if(l==0x7ffffff)
{
d1[x]=0;
// printf("%d %d %d\n",x,q,0);
return 0;
}
d1[x]=l+1;
// printf("%d %d %d\n",x,q,l+1);
return l+1;
}
int dfs(int x,int p)
{
if(d1[x]<=d[x])
{
return 1;
}
int ans=0;
for(int i=0;i<ve[x].size();i++)
{
if(ve[x][i]!=p)
ans+=dfs(ve[x][i],x);
}
return ans;
}
int main()
{
int i,j,k,n,m,x,y,z;
freopen("atlarge.in","r",stdin);
freopen("atlarge.out","w",stdout);
scanf("%d%d",&n,&m);
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
ve[x].push_back(y);
ve[y].push_back(x);
}
dfs1(m,0,-1);
cout<<dfs(m,-1);
}
C:
#include<cstdio>
#include<string>
#include<cstring>
#include<utility>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#include<algorithm>
#include<vector>
#include<iostream>
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define inf 0x7fffffff
#define minn(x,y) x=min(x,y)
#define maxx(x,y) x=max(x,y)
using namespace std;
ll mod=1e9+7;
int s[1000010];
int main()
{
int i,j,k,n,m,x,y,z;
freopen("spainting.in","r",stdin);
freopen("spainting.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for(i=1;i<k;i++)
{
s[i]=(1ll*s[i-1]*m%mod+m)%mod;
}
for(i=k;i<=n;i++)
{
s[i]=(1ll*m*s[i-1]%mod-1ll*(m-1)*s[i-k]%mod+mod)%mod;
}
int sum=1;
for(i=0;i<n;i++)
{
sum=1ll*sum*m%mod;
}
printf("%d",(1ll*sum+mod-(s[n]-s[n-1])%mod)%mod);
}