8.14 Round 1
心态爆炸——
T2小细节出大锅,T3没写%lld,75pts->15pts
T1:https://www.luogu.org/problem/T94043
MST,USACO有原题
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<climits> #include<map> #include<queue> #include<cmath> using namespace std; #define O(x) cout << #x << " " << x << endl; #define B cout << "breakpoint" << endl; #define clr(a) memset(a,0,sizeof(a)); typedef long long ll; inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } const int maxm = 2e6 + 5; const int maxn = 1006; struct egde { int u,v,w; bool operator < (const egde& b) const { return w < b.w; } }e[maxm]; struct node { int x,y; }a[maxn]; int tot; int n,A,b; void adde(int u,int v,int w) { e[++tot].u = u; e[tot].v = v,e[tot].w = w; } int par[maxn],rk[maxn]; void init() { for(int i = 1;i <= maxn - 5;i++) par[i] = i; } inline int find(int x) { return x == par[x] ? x : par[x] = find(par[x]); } inline void merge(int x,int y) { x = find(x); y = find(y); if(x == y) return; if(rk[x] < rk[y]) par[x] = y; else par[y] = x; if(rk[x] == rk[y]) rk[x]++; } int cnt; ll ans; void kruskal() { sort(e + 1,e + 1 + tot); for(int i = 1;i <= tot;i++) { int u = find(e[i].u),v = find(e[i].v); if(u == v) continue; merge(u,v); ans = ans + 1ll * e[i].w; cnt++; if(cnt == n) break; } } int main() { freopen("pupil.in","r",stdin); freopen("pupil.out","w",stdout); init(); n = read(),A = read(),b = read(); for(int i = 1;i <= n;i++) { adde(i,n + 1,A); a[i].x = read(),a[i].y = read(); for(int j = 1;j < i;j++) { int d = abs(a[i].x - a[j].x) + abs(a[i].y - a[j].y); adde(i,j,d * b); } } kruskal(); printf("%lld",ans); }
T2:https://www.luogu.org/problem/T94044
线段覆盖,细节出锅
pos在排序前后对应的线段肯定改变了,没注意到,直接GG
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<climits> #include<map> #include<queue> #include<cmath> using namespace std; #define clr(a) memset(a,0,sizeof(a)); typedef long long ll; inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } const int maxn = 5e5 + 5; struct node { int l,r,id; bool operator < (const node& b) const { if(l == b.l) return r > b.r; return l < b.l; } }a[maxn]; int n,pos,ans = 1; int main() { freopen("cat.in","r",stdin); freopen("cat.out","w",stdout); n = read(); for(int i = 1;i <= n;i++) { int x = read(); a[i].l = i - x,a[i].r = i + x,a[i].id = i; if(a[i].l <= 1 && a[i].r > a[pos].r) pos = i; } sort(a + 1,a + 1 + n); /*for(int i = 1;i <= n;i++) printf("%d %d %d\n",a[i].l,a[i].r,a[i].id); */ for(int i = 1;i <= n;i++) if(a[i].id == pos) { pos = i; break; } int i = pos + 1; while(i <= n) { //O(a[i].r); //O(a[pos].r); int tpos = 0; while(a[i].l <= a[pos].r + 1 && i <= n) { if(a[i].r > a[tpos].r) tpos = i; i++; } pos = tpos,ans++; if(a[pos].r >= n) break; } printf("%d",ans); } /* 10 0 0 0 0 0 0 0 0 0 0 */
T3:https://www.luogu.org/problem/T94046
斜率优化,70pts做法
100pts就在优化的时候把dp数组带上
输出long long的时候一定要用%lld!!!!!不论是否超int
不然在有的评测环境下只有0
75pts:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<climits> #include<map> #include<queue> #include<cmath> using namespace std; #define clr(a) memset(a,0,sizeof(a)); #define int long long typedef long long ll; typedef double db; inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } const int maxn = 1e6 + 5; int sum[maxn],d[maxn],a1[maxn],a2[maxn]; int n,k; int totans; int q[maxn],head,tail,f[maxn]; db get_k(int j,int k) {return (sum[j] * d[j] - sum[k] * d[k]) / (sum[j] - sum[k]); } main() { freopen("life.in","r",stdin); freopen("life.out","w",stdout); n = read(),k = read(); for(int i = 1;i <= n;i++) { a1[i] = read(),a2[i] = read(); sum[i] = sum[i - 1] + a1[i]; } for(int i = n;i >= 1;i--) d[i] = d[i + 1] + a2[i]; for(int i = 1;i <= n;i++) totans += a1[i] * d[i]; if(k == 0) { printf("%lld\n",totans); return 0; } if(k == 1) { int ans = LONG_LONG_MAX,pos = 0; for(int i = 1;i <= n;i++) { int res = totans - sum[i] * d[i]; if(ans > res) ans = res,pos = i; } printf("%lld\n",ans); printf("%lld ",pos - 1); return 0; } if(k == 2) { int ans = LONG_LONG_MAX; int p1,p2; for(int i = 1;i <= n;i++) { while(head < tail) { if(get_k(q[head],q[head + 1]) > d[i]) head++; else break; } while(tail > head) { if(get_k(i,q[tail]) > get_k(q[tail],q[tail - 1])) tail--; else break; } q[++tail] = i; int j = q[head]; int res = totans - d[i] * (sum[i] - sum[j]) - d[j] * sum[j]; if(ans > res) ans = res,p1 = j,p2 = i; } //if(p1 > p2) swap(p1,p2); printf("%lld\n",ans); printf("%lld %lld ",p1 - 1,p2 - 1); puts(""); return 0; } if(k == 3) { int ans = LONG_LONG_MAX; int p1,p2,p3; for(int i = 1;i <= n;i++) for(int j = i + 1;j <= n;j++) for(int k = j + 1;k <= n;k++) { int res = totans - d[i] * sum[i] - d[j] * (sum[j] - sum[i]) - d[k] * (sum[k] - sum[j]); if(ans > res) ans = res,p1 = i,p2 = j,p3 = k; } printf("%lld\n",ans); printf("%lld %lld %lld ",p1 - 1,p2 - 1,p3 - 1); return 0; } } /* 4 3 1 1 2 2 3 3 4 4 */
AC:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<climits> #include<map> #include<queue> #include<cmath> using namespace std; #define clr(a) memset(a,0,sizeof(a)); #define int long long typedef long long ll; typedef double db; inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { (ans *= 10) += ch - '0'; ch = getchar(); } return ans * op; } const int maxn = 1e6 + 5; int sd[maxn],sw[maxn],a1[maxn],a2[maxn],S[maxn],d[maxn],w[maxn]; int n,k; int totans; int q[maxn],head,tail,f[maxn][21],pos[maxn][21],ans[maxn]; db get_k(int x,int y,int k) { db Y = f[x][k - 1] - f[y][k - 1] + S[x] - S[y],X = sw[x] - sw[y]; return Y / X; } main() { freopen("life.in","r",stdin); freopen("life.out","w",stdout); n = read(),k = read(); for(int i = 1;i <= n;i++) { w[i] = read(),d[i] = read(); sw[i] = sw[i - 1] + w[i]; sd[i] = sd[i - 1] + d[i - 1]; S[i] = S[i - 1] + sd[i] * w[i]; } sd[n + 1] = sd[n] + d[n]; sw[n + 1] = sw[n],S[n + 1] = S[n]; memset(f,0x3f,sizeof(f)); f[0][0] = 0; for(int j = 1;j <= k + 1;j++) { for(int i = 1;i <= n + 1;i++) { while(head < tail) { if(get_k(q[head + 1],q[head],j) <= sd[i]) head++; else break; } while(tail > head) { if(get_k(i,q[tail],j) <= get_k(q[tail],q[tail - 1],j)) tail--; else break; } q[++tail] = i; int t = q[head]; pos[i][j] = t; f[i][j] = f[t][j - 1] - sd[i] * sw[t] + S[t] + sd[i] * sw[i] - S[i]; } head = tail = 0; } printf("%lld\n",f[n + 1][k + 1]); int now = n+1,tt = k+1; while(now) { ans[++ans[0]] = pos[now][tt]; now = ans[ans[0]],tt--; } for(int i = ans[0]-1;i>=1;--i)printf("%lld ",ans[i]-1); } /* 4 3 1 1 2 2 3 3 4 4 */