前言
感觉不难呀
JZOJ 3054 祖孙询问
题目
求两个树上节点的祖孙关系
分析
树上倍增LCA模板,不想多说
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int N=40011;
struct node{int y,next;}e[N<<1];
int n,ls[N],bj[N],f[N][17],dep[N],k=1,root,tot;
inline signed iut(){
rr int ans=0,f=1; rr char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans*f;
}
inline void add(int x,int y){
e[++k]=(node){y,ls[x]}; ls[x]=k;
e[++k]=(node){x,ls[y]}; ls[y]=k;
}
inline void dfs(int x,int fa){
for (rr int i=ls[x];i;i=e[i].next)
if (e[i].y!=fa){
dep[e[i].y]=dep[x]+1;
f[e[i].y][0]=x;
dfs(e[i].y,x);
}
}
inline signed lca(int x,int y){
if (x==y) return x;
if (dep[x]<dep[y]) x^=y,y^=x,x^=y;
for (rr int i=16;~i;--i) if (dep[x]-(1<<i)>=dep[y]) x=f[x][i];
if (x==y) return x;
for (rr int i=16;~i;--i)
if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
if (x==y) return x;
else return f[x][0];
}
signed main(){
n=iut(); memset(f,-1,sizeof(f));
for (rr int i=1;i<=n;++i){
rr int x=iut(),y=iut();
if (!bj[x]) bj[x]=++tot;
if (y!=-1&&!bj[y]) bj[y]=++tot;
if (y==-1) root=bj[x];
else add(bj[x],bj[y]);
}
dep[root]=1; dfs(root,0); n=tot;
for (rr int j=1;(1<<j)<=n;++j)
for (rr int i=1;i<=n;++i) if (f[i][j-1])
f[i][j]=f[f[i][j-1]][j-1];
for (rr int m=iut();m;--m){
rr int x=bj[iut()],y=bj[iut()];
rr int t=lca(x,y);
if (t==x) putchar(49);
else if (t==y) putchar(50);
else putchar(48);
putchar(10);
}
return 0;
}
JZOJ 3055 比赛
题目
每个选手都有一个非负的实力值。如果实力值为
X
X
X和
Y
Y
Y的选手对抗,那么实力值较强的选手所在的队伍将会获得
(
X
−
Y
)
2
(X-Y)^2
(X−Y)2的得分。
求
A
A
A队伍的得分减
B
B
B队伍的得分的期望值。
分析
O ( n 2 ) O(n^2) O(n2)代码是行不通的,所以尝试用双指针 O ( n ) O(n) O(n),枚举到 i i i点,记录隔壁队伍不超过该实力的前缀和以及前缀平方和,然后把完全平方公式拆开分别求解
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
typedef long long ll;
int n,a[50001],b[50001];
ll sum,sqrr,sumb,sqrb,ans;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
signed main(){
n=iut();
for (rr int i=1;i<=n;++i) a[i]=iut();
for (rr int i=1;i<=n;++i) b[i]=iut();
sort(a+1,a+1+n); sort(b+1,b+1+n);
for (rr int i=1;i<=n;++i) sum+=b[i],sqrr+=1ll*b[i]*b[i];
for (rr int i=1,j=0;i<=n;++i){
while (a[i]>b[j]&&j<=n) sumb+=b[j],sqrb+=1ll*b[j]*b[j],++j;
ans+=1ll*a[i]*a[i]*((j<<1)-n-2)+((sum-(sumb<<1))*a[i]<<1)-sqrr+(sqrb<<1);
}
return !printf("%.1lf",ans*1.0/n);
}
JZOJ 3056 数字
题目
一个数字被称为好数字当他满足下列条件:
- 它有 2 n 2n 2n个数位, n n n是正整数(允许有前导0)
- 构成它的每个数字都在给定的数字集合 S S S中。
- 它前 n n n位之和与后 n n n位之和相等或者它奇数位之和与偶数位之和相等
已知 n n n,求合法的好数字的个数 m o d mod mod 999983 999983 999983。
分析
可以用01背包的方法求出方案,因为前
n
n
n位之和=后
n
n
n位之和,奇数位之和=偶数位之和,所以前
n
n
n位中奇数位之和=后
n
n
n位中偶数位之和 且
前
n
n
n位中偶数位之和=后
n
n
n位中奇数位之和,所以处理出
n
,
⌊
n
2
⌋
n,\lfloor\frac{n}{2}\rfloor
n,⌊2n⌋和
⌈
n
2
⌉
\lceil\frac{n}{2}\rceil
⌈2n⌉时01背包的方案,然后用容斥求解
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define rr register
using namespace std;
const int mod=999983;
typedef long long ll; int n,len,b[11];
ll ans,ans1,ans2,f[2][9101];
inline void init(){
scanf("%d",&n); rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) b[++len]=c^48,c=getchar();
sort(b+1,b+1+len);
}
inline ll modd(ll ans){
rr int f=1;
if (ans<0) f=-f,ans=-ans;
if (ans>=(mod<<4)) ans=(ans-(mod<<4))%mod;
else {
ans-=(ans>=(mod<<3)?(mod<<3):0),
ans-=(ans>=(mod<<2)?(mod<<2):0),
ans-=(ans>=(mod<<1)?(mod<<1):0),
ans-=(ans>=(mod<<0)?(mod<<0):0);
}
return ans*f;
}
signed main(){
init(); f[0][0]=1; rr int t1=n>>1,t2=(n+1)>>1;
if (!t1) ans1=1;
for (rr int i=1;i<=n;++i){
memset(f[i&1],0,sizeof(f[i&1]));
for (rr int j=0;j<=b[len]*i;++j)
for (rr int p=1;p<=len;++p)
if (b[p]<=j) f[i&1][j]=modd(f[i&1][j]+f[(i&1)^1][j-b[p]]);
if (i==t1)
for (rr int j=0;j<=b[len]*i;++j) ans1=modd(ans1+f[i&1][j]*f[i&1][j]);
if (i==t2)
for (rr int j=0;j<=b[len]*i;++j) ans2=modd(ans2+f[i&1][j]*f[i&1][j]);
if (i==n)
for (rr int j=0;j<=b[len]*i;++j) ans=modd(ans+(f[i&1][j]*f[i&1][j]<<1));
}
return !printf("%lld",modd(modd(ans-ans1*ans2)+mod));
}

本文介绍了三道算法竞赛题目的解题思路及代码实现,包括树上倍增LCA模板解决祖孙关系查询问题、双指针法求解队伍得分期望值问题以及使用01背包和容斥原理计算好数字的个数。
458

被折叠的 条评论
为什么被折叠?



