給定一條直線上$n$個點,要求去掉最少的點,使得直線上相距最遠的兩個點的距離$\leq d$.c++
枚舉長度爲$d$的區間。數組
#include <bits/stdc++.h> #define F(i, a, b) for (int i = (a); i < (b); ++i) #define F2(i, a, b) for (int i = (a); i <= (b); ++i) #define dF(i, a, b) for (int i = (a); i > (b); --i) #define dF2(i, a, b) for (int i = (a); i >= (b); --i) using namespace std; typedef long long LL; int a[110]; int main() { int n, d; scanf("%d%d", &n, &d); F(i, 0, n) { int x; scanf("%d", &x); ++a[x]; } F2(i, 1, 100) a[i] += a[i-1]; int ans = min(a[100]-a[d], a[99-d]); F(i, 1, 100-d) { int l = i, r = i+d; ans = min(ans, a[l-1]+a[100]-a[r]); } printf("%d\n", ans); return 0; }
初始數爲$n$,兩種操做:spa
求最小代價使$n$變爲$1$.code
一旦某一次除法的代價$\gt$減法的(等效)代價,則直接減到$1$,不然進行除法操做。隊列
#include <bits/stdc++.h> #define F(i, a, b) for (int i = (a); i < (b); ++i) #define F2(i, a, b) for (int i = (a); i <= (b); ++i) #define dF(i, a, b) for (int i = (a); i > (b); --i) #define dF2(i, a, b) for (int i = (a); i >= (b); --i) using namespace std; typedef long long LL; int main() { LL n,k,a,b; scanf("%I64d%I64d%I64d%I64d",&n,&k,&a,&b); LL ans = 0; bool flag = false; while (n!=1) { if (n%k) { ans += n%k*a; n = n/k*k; } if (n/k*(k-1)*a <= b) { ans += (n-1)*a; break; } ans += b; n /= k; } printf("%I64d\n", ans); return 0; }
在字符集$\sum$範圍內,求長度爲$k$的,比給定字符串$s$大的,最小的字符串。字符串
記$len=|s|$,get
#include <bits/stdc++.h> #define F(i, a, b) for (int i = (a); i < (b); ++i) #define F2(i, a, b) for (int i = (a); i <= (b); ++i) #define dF(i, a, b) for (int i = (a); i > (b); --i) #define dF2(i, a, b) for (int i = (a); i >= (b); --i) #define maxn 100010 using namespace std; typedef long long LL; char s[maxn]; int mp[256], ch[30], a[maxn]; bool vis[256]; int main() { int n, k, tot=0; scanf("%d%d", &n,&k); scanf("%s",s); int len = strlen(s); F(i, 0, len) { if (tot==26) break; if (!vis[s[i]]) { ch[tot++] = s[i]; vis[s[i]] = true; } } sort(ch, ch+tot); F(i, 0, tot) mp[ch[i]] = i; if (k>len) { while (len<k) s[len++] = ch[0]; s[len] = '\0'; puts(s); return 0; } s[k] = '\0'; F(i, 0, k) a[i] = mp[s[i]]; int i = k-1; while (true) { ++a[i]; if (a[i]<tot) break; a[i--] = 0; } F(i, 0, k) s[i] = ch[a[i]]; puts(s); return 0; }
給定數組$a$,按必定的規則能夠生成數組$b$. 規則以下:it
- $b_1=b_2=b_3=b_4=0.$
- For all $5\leq i\leq n$: --- $b_i=0$ if $a_i,a_{i-1},a_{i-2},a_{i-3},a_{i-4}\gt r$ and $b_{i-1},b_{i-2},b_{i-3},b_{i-4}=1$ --- $b_i=1$ if $a_i,a_{i-1},a_{i-2},a_{i-3},a_{i-4}\lt l$ and $b_{i-1},b_{i-2},b_{i-3},b_{i-4}=0$ --- $b_i=b_{i-1}$ otherwise
只需肯定每一個轉折點,對於其及其前面共$5$個數字,由$1$變爲$0$則取最小值使$r$比它小,由$0$變爲$1$則取最大值使$l$比它大。class
至於中間則無需考慮,由於題目保證有解,而要不發生變化,即條件不成立,則只要$l$儘可能小,$r$儘可能大便可。test
#include <bits/stdc++.h> #define F(i, a, b) for (int i = (a); i < (b); ++i) #define F2(i, a, b) for (int i = (a); i <= (b); ++i) #define dF(i, a, b) for (int i = (a); i > (b); --i) #define dF2(i, a, b) for (int i = (a); i >= (b); --i) #define inf 1000000000 #define maxn 100010 using namespace std; char s[maxn]; int a[maxn]; typedef long long LL; int minn(int p) { int ret = a[p]; F(i, p+1, p+5) ret = min(ret, a[i]); return ret; } int maxx(int p) { int ret = a[p]; F(i, p+1, p+5) ret = max(ret, a[i]); return ret; } int main() { int n; scanf("%d", &n); F(i, 0, n) scanf("%d", &a[i]); scanf("%s", s); bool flag = false; int r = inf, l = -inf; F(i, 0, n) { if (s[i]-'0'!=flag) { if (flag) r = min(r, minn(i-4)-1); else l = max(l, maxx(i-4)+1); flag = !flag; } } printf("%d %d\n", l, r); return 0; }
給定一個數組,將其分割成若干段,將每一段的$value$求和,要求得最小值。
$value$定義以下: 對於長度爲$k$的數組$b$,其$value$爲除了$\lfloor\frac{k}{c}\rfloor$小元素之外的元素的和。 例如:[3,1,6,5,2], c=2,其value爲3+6+5=14.
首先一個顯然的事實是:假設不分段而做爲一個總體能去除掉$m$個元素,那分段去除掉的元素個數必然$\leq m$.
然而又有另外一個顯然的事實:不分段去掉$m$個元素之和$sum1$,與分段去掉$m$個元素$sum2$相比,顯然$sum1\leq sum2$. 由於不分段的話去掉的是一整段的$m$個最小,而分段的話去掉的是$m$段中每段中的最小。
綜合上面兩個事實,應該儘可能多分段,又要保證每一段分的有價值,即,最理想的狀況就是每$c$個元素分一段。
因而$dp$以下:
$dp[i] = min(dp[i-1]+a[i], dp[i-c]+sum[i-c+1..i]-min[i-c+1..i])$
至於最小值,直接用ST表進行RMQ便可,比賽時用的是單調隊列維護的...。
#include <bits/stdc++.h> #define F(i, a, b) for (int i = (a); i < (b); ++i) #define F2(i, a, b) for (int i = (a); i <= (b); ++i) #define dF(i, a, b) for (int i = (a); i > (b); --i) #define dF2(i, a, b) for (int i = (a); i >= (b); --i) #define maxn 100010 using namespace std; typedef long long LL; LL a[maxn], sum[maxn], dp[maxn]; int st[maxn]; int main() { int n, c; scanf("%d%d", &n, &c); F2(i, 1, n) { scanf("%I64d", &a[i]); sum[i] = sum[i-1] + a[i]; } if (c==1) { printf("%d\n", 0); return 0; } dp[1] = a[1]; int l=0, r=0; st[r++] = 1; F2(i, 2, n) { LL minn = dp[i-1]+a[i]; while (r>l && a[st[r-1]]>=a[i]) --r; st[r++] = i; if (i-c>=0) { while (r>l && st[l]<=i-c) ++l; minn = min(minn, dp[i-c]+sum[i]-sum[i-c]-a[st[l]]); } dp[i] = minn; } printf("%I64d\n", dp[n]); return 0; }