第十九届浙大城市学院程序设计竞赛
第十九届浙大城市学院程序设计竞赛
E Disjoint Path On Tree
题意:求树上不相交简单路径对的数量
做法:其实很容易想到,我们需要求f1[x]表示经过x点的子树内的简单路径数,f2[x]表示子树x的内的简单路径数量,但是统计数量的时候赛时我想的复杂了一些,因为还需要换根求一下各种值,但其实我们发现m个点构成的子树内简单路径数量就是其中数对的数量m*(m+1)/2,因为任意两点都存在简单路径,那么计算方法就简单了,就等于\(f1[x]*m(m+1)/2\),m=n-f3[x],f3[x]表示x子树大小,但是我们考虑这样计算,其实每个子树的各个儿子之间的数量都被重复计算了,我们需要剪掉这部分,也就是剪掉f2[v]的,v是x的子节点
点击查看代码
#include
using namespace std;
const int maxn=2e5+10;
typedef long long ll;
vectorG[maxn];
ll f1[maxn],f2[maxn],f3[maxn],dp[maxn];
const ll mod=1e9+7;
ll ans=0;
int n;
void init(int n){
for (int i=1;i<=n;i++) G[i].clear(),dp[i]=f1[i]=f2[i]=f3[i]=0;
}
ll quickpow(ll a,ll b){
ll p=1;
for (;b;b>>=1){
if(b&1ll) p=p*a%mod;
a=a*a%mod;
}
return p%mod;
}
void dfs(int x,int f){
f3[x]=f1[x]=1;
for (int i=0;i>T;
while(T--){
ans=0;
scanf("%d",&n);
if(n==1 || n==2) {
if(n==1) printf("0\n");
else {
int x,y;
cin>>x>>y;
printf("1\n");
}
continue;
}
init(n);
for (int i=1;i
H Distance
题意:给定多个线段,要求一个中间点,使得到各个线段的距离都最短
做法:其实们就是选一个中点即可,因为中点的性质就是到一条线段上其它点的和最小,所以我们只需要对顶堆维护中点值即可,现在我们来考虑怎么计算距离之和,1.对于一个线段,如果其值位于现在中点的两边,那么答案贡献不增加。2.对于一条线段右端点r<中点,那么中点的值会改变,但是我们思考中点移动会改变当前的吗?在中点移动后并未使左右线段数量改变的前提下其实答案不会变,所以我们只需要考虑新加进来的点产生的贡献,贡献即为中点值top-r。3.对于l大于中点也是类似的加入贡献即可
点击查看代码
#include
using namespace std;
typedef long long ll;
priority_queue,less >Q1;
priority_queue,greater >Q2;
int main(){
#ifdef lmj_debug
freopen("1.in","r",stdin);
#endif
int n;
ll ans=0;
cin>>n;
Q1.push(-1e9-10);
Q2.push(1e9+10);
for (int i=1;i<=n;i++){
int l,r;
scanf("%d%d",&l,&r);
if(rQ2.top()){
ans+=(l-Q2.top());
Q1.push(Q2.top());
Q2.pop();
Q2.push(l);
Q2.push(r);
}else Q1.push(l),Q2.push(r);
printf("%lld\n",ans);
}
return 0;
}
J Substring Inversion (Easy Version)
做法:其实比较简单就是直接暴力处理出所有字串然后排序,\(n^3logn\),考虑到a
点击查看代码
#include
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int sum[550];
vector< pair >a;
int main(){
#ifdef lmj_debug
freopen("1.in","r",stdin);
#endif
int T;
cin>>T;
while(T--){
a.clear();
int n;
string s;
cin>>n>>s;
for (int i=0;i
后缀数组做法:
F Sum of Numerators
做法:其实很简单,但是当时还是想了一小会儿,我们直接通过2^x幂去筛就行了,然后x要小于k,因为x-1筛出来的必定含有x的,所以还要将x筛出来的方案减一下就ok了
点击查看代码
#include
using namespace std;
typedef long long ll;
ll phi[40];
int main(){
#ifdef lmj_debug
freopen("1.in","r",stdin);
#endif
for (int i=0;i<=32;i++) phi[i]=(1ll<>T;
while(T--){
ll n,k;
scanf("%lld%lld",&n,&k);
ll ans=0;
ll p=n/2ll;
if(n&1ll) p++;
ans+=((p)+(p*(p-1)));
if(k>32) k=32;
ll last=0;
for (int i=k;i>=1;i--){
ll x=n/phi[i];
ll o=(x+(x*(x-1)/2));
ans+=o;
ans-=last;
last=o*2ll;
}
if(k==0) {
p=n/2ll;
ans+=((2ll*p)+(p*(p-1)));
}
printf("%lld\n",ans);
}
return 0;
}