A 农夫约的假期
在某国有一个叫农夫约的人,他养了很多羊,其中有两头名叫mm和hh,他们的歌声十分好听,被当地人称为“魔音”······
农夫约也有自己的假期呀!他要去海边度假,然而mm和hh不能离开他。没办法,他只好把他们两个带上。
到了海边,农夫约把他的羊放在一个(nn)的矩阵(有nn个方格)里。mm和hh十分好动,他们要走到m(m<=n*n)个地方,第i个地方的坐标为(x[i](行),y[i](列)),每到一个地方他们会高歌一曲,制造q[i]点魔音值,因为他们的魔音十分独特,他们的声音只能横着或竖着传播。每传播一格,魔音值会增加1。(传播的格子数取最小的)接下来农夫约要住酒店。为了方便照顾小羊们,他选的酒店的坐标要在矩阵内。但小羊们的魔音让他十分头疼。他想求出魔音值最小的地方。
他还要享受他的假期,所以他把这个任务交给你了,加油(_)。
求中位数即可
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,z;
int x[100005],y[100005],q[100005];
int main(){
scanf("%d%d%d",&n,&m,&z);
for (int i=1;i<=m;i++)
scanf("%d%d%d",&x[i],&y[i],&q[i]);
sort(x+1,x+1+m);
sort(y+1,y+1+m);
int cx,cy;
long long ans=0;
cx=x[m/2];cy=y[m/2];
if (m%2==1){
cx=x[m/2+1];cy=y[m/2+1];
}
for (int i=1;i<=m;i++)
ans+=abs(x[i]-cx)*z+abs(y[i]-cy)*z+q[i];
printf("%lld\n",ans);
printf("%d %d",cx,cy);
}
B 小x游世界树
小x得到了一个(不可靠的)小道消息,传说中的神岛阿瓦隆在格陵兰海的某处,据说那里埋藏着亚瑟王的宝藏,这引起了小x的好奇,但当他想前往阿瓦隆时发现那里只有圣诞节时才能到达,然而现在已经春天了,不甘心的他将自己的目的地改成了世界树,他耗费了大量的时间,终于将自己传送到了世界树下。世界树是一棵非常巨大的树,它有着许许多多的枝条以及节点,每个节点上都有一个平台。好不容易来到传说中的世界树下,小x当然要爬上去看看风景。小x每经过一条边都会耗费体力值。然而世界树之主想给他弄(gáo)些(dǐan)麻(shì)烦(qíng),于是他在每条边上都设了一个魔法阵,当小x踏上那条边时会被传送回根节点,魔法阵只生效一次。这岂不是要累死小x?幸运的是,每个平台上都有无数个加速器,这些加速器可以让小x在当前节点所连的边上耗费的体力值减少,不同平台的加速器性能不一定相同,但同一个平台的加速器性能绝对相同。世界树之主给了小x一次“换根”的机会,他可以将世界树的任何一个节点变为根,但所有的边都不能改变。小x想问你,将根换为哪个节点能使小x爬到世界树上的每个节点耗费的体力值和最少。默认编号为1的点为初始根。
下面是一个修改中未完成的程序
#include <cstdio>
#include <cstring>
using namespace std;
int n,ans,st,cnt;
int a[700005];
int ls[700005],ne[700005],to[700005],d[700005];
int b[700005],f[700005],son[700005];
void dfs(int k){
b[k]=1;
int u=ls[k],bz=0,bbz=0;
while (u){
if (!b[to[u]]){
int ccd=(son[k]-son[to[u]])*d[u^1]-son[to[u]]*d[u];
f[to[u]]+=ccd+f[k];
if (f[to[u]]<ans){ans=f[to[u]];st=to[u];}
dfs(to[u]);
}
u=ne[u];
}
}
void dfs1(int k){
b[k]=1;
son[k]=1;
int u=ls[k];
int sss=f[k];
while (u){
if (!b[to[u]]){
f[to[u]]=f[k]+d[u];
dfs1(to[u]);
son[k]+=son[to[u]];
sss+=f[to[u]];
}
u=ne[u];
}
f[k]=sss;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
cnt=1;
for (int i=1;i<n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
ne[++cnt]=ls[x];ls[x]=cnt;to[cnt]=y;d[cnt]=z-a[x];
ne[++cnt]=ls[y];ls[y]=cnt;to[cnt]=x;d[cnt]=z-a[y];
}
memset(b,0,sizeof(b));
memset(f,0,sizeof(f));
dfs1(1);
ans=f[1];st=1;
memset(b,0,sizeof(b));
dfs(1);
printf("%d\n",st);
printf("%d",ans);
}
C 观察
出题人给出一颗以1为根的树,一开始每个节点都是一颗棋子,一面白一面黑,白色的面朝上
接下来就q次操作,操作分两种
0操作 将一个颗棋子翻转
1操作 询问一颗棋子与所有面朝上为黑色的棋子lca最深的那个的编号