E
質問の意味:木n個の点、あなたがパスを見つけることができるかどうか尋ね、そのルート上のいずれかのk点を、いずれかのパスの長さが1であるから考えます。
分析: LCA
#include <cstdioを>
する#include <CStringの>
する#include <cstdlib>
の#include <cmath>
の#include <アルゴリズム>
の#include <ストリング>
の#include <iostreamの>
する#include <セット>
の#include <マップ>
の#include <積層>
書式#include <キュー>
の#include <ベクトル>
の#include <sstream提供>
typedefの長い長いLL。
const int型INF = 0x3f3f3f3f。
名前空間stdを使用。
const int型MAXN = 200000 + 10。
const int型LOG_MAXN = 18;
constのダブルEPS = 1E-8;
INT DCMP(ダブルA、ダブルB){
IF(ファブ( - B)<EPS)戻り0;
<bを返しますか?-1:1;
}
ベクトル<整数> G [MAXN]。
整数N、M。
ベクトル<整数> V。
ボイドDFS(int型V、INT P、int型のD){
深さ[V] = D。
親[0] [V] = P。
INT LEN = G [V] .size()。
以下のために(INT I 0 =; I <LEN; ++ I){
IF(G [V] [I] = P!){
DFS(G [V] [i]は、V、D + 1)。
}
}
}
ボイドのinit(){
DFS(1、-1、0);
用(int型のk = 0; K + 1 <LOG_MAXN; ++ K){
ための(int型V = 1; V <= N; ++ V){
IF(親[K] [V] == -1)親[K + 1] [V] = -1。
他{
親[K + 1] [V] =親[K] [親[K] [V]]。
}
}
}
}
BOOL CMP(CONST INT&、CONST INT&B){
戻り深さ[A] <深さ[B]。
}
int型LCA(INT U、V INT){
IF(深さ[U]>深さ[V]){
スワップ(U、V)。
}
(int型のk = 0; K <LOG_MAXN; ++ k)に対する{
IF((深さ[U] -深さ[V])>> K&1){
V =親[K] [V]。
}
}
もし(U == V)Uを返します。
{ - (; K> = 0 --k 1のint K = LOG_MAXN)のための
(親[K] [U] =親[K] [V]!){もし
[U] U =親[K]。
V =親[K] [V]。
}
}
戻り親[0] [U]。
}
int型のmain(){
scanf関数( "%D%D"、&N、&M)。
以下のために(INT I 0 =、I <N - 1; ++ I){
scanf関数( "%D%D"、およびX&Y)。
G [X] .push_back(Y)。
G [Y] .push_back(X)。
}
のinit();
一方、(M - ){
int型K。
scanf関数( "%のD"、&K);
V.clear();
一方、(K - ){
scanf関数( "%のD"、&x)は、
V.push_back(X)。
}
ソート(V.begin()、V.end()、CMP)。
INT LEN = V.size()。
OK =真BOOL;
以下のために(INT I 1 =; I <LEN; ++ I){
int型TMP = LCA(V [i]は、V [I - 1])。
IF(深さ[V [I]] -深さ[TMP]> 1つの&&深さ[V [I - 1] -深さ[TMP]> 1){
OK = FALSE;
}
}
であれば(OK)のprintf( "YES \ n");
他のprintf( "NO \ N");
}
0を返します。
}
F
問題の意味: n個の点は、2つの操作を可能にする、ある:(1)最小の数プラス1(2)最大数から1を引いたものは、kの数に等しくすることができ、最小限の操作を数回尋ねます。
分析:トラバース列挙答えが最小値をとります。ばかりを右折、左に取ることができ、両側が取ります。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<sstream>
typedef long long LL;
const int INF = 0x3f3f3f3f;
using namespace std;
const int MAXN = 200000 + 10;
const double eps = 1e-8;
int dcmp(double a, double b){
if(fabs(a - b) < eps) return 0;
return a < b ? -1 : 1;
}
LL a[MAXN], pre[MAXN], suf[MAXN];
map<LL, LL> l, r;
int main(){
LL n, k;
scanf("%lld%lld", &n, &k);
for(LL i = 1; i <= n; ++i){
scanf("%lld", &a[i]);
}
sort(a + 1, a + n + 1);
for(LL i = 1; i <= n; ++i){
pre[i] = pre[i - 1] + a[i];
if(!l[a[i]]){
l[a[i]] = i;
}
}
for(LL i = n; i >= 1; --i){
suf[i] = suf[i + 1] + a[i];
if(!r[a[i]]) r[a[i]] = i;
}
LL ans = 1000000000000000;
for(LL i = 1; i <= n; ++i){
LL cnt = r[a[i]] - l[a[i]] + 1;
if(cnt >= k){
ans = 0;
break;
}
LL cost1, cost2;
cost1 = (a[i] - 1) * (i - 1) - pre[i - 1];
cost2 = suf[r[a[i]] + 1] - (a[i] + 1) * (n - r[a[i]]);
if(cnt + i - 1 >= k){
ans = min(ans, cost1 + k - cnt);
}
if(cnt + n - r[a[i]] >= k){
ans = min(ans, cost2 + k - cnt);
}
ans = min(ans, cost1 + cost2 + k - cnt);
i += cnt - 1;
}
printf("%lld\n", ans);
return 0;
}