2018年9月23日提高組
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最深的那個的編號