略方法就是把疲勞值從小到大排個序,然後從尾部開始乙個乙個取,當選到第i(i >= 2)個時有2種取法:一是取,那麼x = i的答案就是[n-i+1,n]區間的疲勞值求和並加上其中最大距離的2倍;二是不取,那麼答案便是[n-i+2,n]區間的疲勞值求和並加上[1,n-i]區間中(疲勞值+距離的2倍)最大的乙個,為什麼一定是前面那個最大?因為如果最大距離在[n-i+2,n]中,那顯然是選取n-i的地方更增加疲勞值。2種取法取個最大即可。
最大的疑問是,為什麼x=i時的最優解一定是建立在[n-i+2,n]區間中的數全部取完之後呢?
證明如下:
當i = 2時,第n個數是必取的,可以用反證法證明:假設取第x,y(x當i > 2時,也可以用反證法證明:假設在[n-i+2,n]中取m(m
1 #include 2view codeusing
namespace
std;34
#define rep(i,n) for (int i = 0; i < (n); ++i)
5#define for(i,s,t) for (int i = (s); i <= (t); ++i)
6#define rfor(i,t,s) for (int i = (t); i >= (s); --i)
7#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
8#define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)910
#define pr(x) cout << #x << " = " << x << " "
11#define prln(x) cout << #x << " = " << x << endl
1213
#define all(x) x.begin(),x.end()
14#define ins(x) inserter(x,x.begin())
1516
#define ms0(a) memset(a,0,sizeof(a))
17#define msi(a) memset(a,inf,sizeof(a))
1819
#define pii pair20
#define piii pair,int>
21#define mp make_pair
22#define pb push_back
23#define fi first
24#define se second
2526 inline int
gc()
3334 inline int
ri()
4041 typedef long
long
ll;42
const
int maxn = 1e5 + 7;43
44int
n; 45
intdist[maxn], cost[maxn];
46int suffixmax[maxn]; //
記錄dist的字尾最大值
47int f[maxn]; //
f[i]表示當x=1時在1~i範圍內只選擇1家住戶的最優解
48int prefixsum[maxn]; //
cost的字首和
4950
int getsum(int x, int
y)53
54void mergesort(int l, int
r)69
else73}
74while(i <=mid)
79while(j <=r)
8485
rep(i, k)89}
9091
intmain()
NOIP 2015 普及組 初賽
noip 2015 普及組 初賽 疑難點 學習 感悟。本份試卷本人得分93,兩處錯誤,一錯在二 1.題,眼花了,多數了個資料3241 二錯在四 2.題 5 空,該空寫成rbound mid 1,這個錯誤在考試中是改正不了的,這是由本人解題方法決定的。也就是說該份試卷本人的極限是98。1.c.1000...
NOIP2015 普及組 金幣
題目描述 國王將金幣作為工資,發放給忠誠的騎士。第一天騎士收到一枚金幣 之後兩天 第二天和第三天 每天收到兩枚金幣 之後三天 第 四 五 六天 每天收到三枚金幣 之後四天,每天收到四枚金幣,以此類推 這種工資發放模式會一直延續下去,當連續n天收到n枚金幣後,騎士會在之後的n 1天,每天收到n 1枚金...
NOIP2015 普及組複賽 第一題 金幣
題目描述description 國王將金幣作為工資,發放給忠誠的騎士。第一天,騎士收到一枚金幣 之後兩天 第二天和第三天 每天收到兩枚金幣 之後三天 第 四 五 六天 每天收到三枚金幣 之後四天 第 七 八 九 十天 每天收到四枚金幣 這種工資發放模式會一直這樣延續下去 當連續n天每天收到n枚金幣後...