ABC 210
阿新 • • 發佈:2021-07-18
A
按題意模擬。
scanf("%lld%lld%lld%lld",&n,&a,&x,&y);
std::cout<<n * x - (x - y) * std::max(n - a,0ll);
B
判斷第一個 \(1\) 的位置的奇偶性。
scanf("%lld",&n); scanf("%s",a + 1); for(int i = 1;i <= n;++i){ if(a[i] == '1'){ if(i % 2) puts("Takahashi"); else puts("Aoki"); return 0; } }
C
用 \(map\) 記錄每個 \(k\) 長度區間的每個顏色的出現情況。
每次向右移一位,則把前者移除,後者加入。
scanf("%lld%lld",&n,&k); for(int i = 1;i <= n;++i){ scanf("%lld",&c[i]); } ll now = 0,ans = 0; for(int i = 1;i <= k;++i){ QWQ[c[i]] ++ ; if(QWQ[c[i]] == 1) now ++ ; } ans = now; for(int i = k + 1;i <= n;++i){ QWQ[c[i - k]] -- ; if(QWQ[c[i - k]] == 0) now -- ; QWQ[c[i]] ++ ; if(QWQ[c[i]] == 1) now ++ ; ans = std::max(now,ans); } std::cout<<ans<<std::endl;
D
考慮先考慮行的貢獻,先把 \(a_{i,j} \to a_{i,j} + i * c\) ,並預處理出每行每列下的最小值。
然後我們按列按行列舉,在列舉第 \(i\) 列時,先把對應的行下的最小值區間,把 \([1,i]\) 加 \(c\),\([i + 1,n]\) 減 \(c\) ,可以使用線段樹維護,然後查詢最小值就好了。
同時要考慮在同行的操作,複雜度 \(O(nlogn)\) 。
#include<iostream> #include<cstdio> #include<cstring> #include<map> #define ll long long #define N 1005 #define lowbit(x) (x & -x) ll a[N][N],k[N][N],pre[N][N],s[N][N]; ll h,w,c; struct P{ ll v,tag; P(){v = tag = 0;} }; struct segment{ P t[N << 2]; #define ls(x) (x << 1) #define rs(x) (x << 1 | 1) #define mid ((l + r) >> 1) inline void up(int u){ t[u].v = std::min(t[ls(u)].v,t[rs(u)].v); } inline void push_down(int u){ if(t[u].tag){ t[ls(u)].v += t[u].tag; t[ls(u)].tag += t[u].tag; t[rs(u)].v += t[u].tag; t[rs(u)].tag += t[u].tag; t[u].tag = 0; } } inline void add(int u,int l,int r,int tl,int tr,ll p){ if(tl <= l && r <= tr){ t[u].v += p; t[u].tag += p; return ; } push_down(u); if(tl <= mid) add(ls(u),l,mid,tl,tr,p); if(tr > mid) add(rs(u),mid + 1,r,tl,tr,p); up(u); } }e[N]; ll ans = 9e18; ll f[N]; int main(){ scanf("%lld%lld%lld",&h,&w,&c); for(int i = 1;i <= h;++i) for(int j = 1;j <= w;++j) scanf("%lld",&a[i][j]),k[i][j] = a[i][j]; for(int i = 1;i <= h;++i) for(int j = 1;j <= w;++j) k[i][j] += i * c; // for(int i = 1;i <= h;++i,puts("")) // for(int j = 1;j <= w;++j) // std::cout<<k[i][j]<<" "; for(int i = 1;i <= w;++i) for(int j = h;j >= 1;--j){ if(j == h)continue; k[j][i] = std::min(k[j + 1][i],k[j][i]); } for(int i = 1;i <= h;++i) for(int j = 1;j <= w;++j) k[i][j] += (j - 1)*c; // for(int i = 1;i <= h;++i,puts("")) // for(int j = 1;j <= w;++j) // std::cout<<k[i][j]<<" "; // puts(""); for(int i = 1;i <= h;++i) for(int j = 1;j <= w;++j) e[i].add(1,1,w,j,j,k[i][j]); // for(int j = 1;j <= w;++j) // for(int i = 1;i <= h;++i) // std::cout<<e[i].t[1].v<<std::endl; for(int i = 1;i <= h - 1;++i) ans = std::min(ans,1ll * e[i + 1].t[1].v + a[i][1] - i * c); for(int i = 2;i <= w;++i) for(int j = 1;j <= h - 1;++j){ e[j + 1].add(1,1,w,1,i - 1,c); e[j + 1].add(1,1,w,i,w,-c); ans = std::min(ans,1ll * e[j + 1].t[1].v + a[j][i] - j * c); } for(int i = 1;i <= h;++i){ std::memset(f,0x7f,sizeof(f)); for(int j = 1;j <= w;++j){ if(j != 1) f[j] = f[j - 1] + c; ans = std::min(ans,f[j] + a[i][j]); f[j] = std::min(f[j],a[i][j]); } } std::cout<<ans<<std::endl; }
F
維護迴圈節就好。
按代價排序,並維護迴圈節至 \(1\) 。
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
pii a[100005];
int gcd(int x, int y) { return y == 0 ? x : gcd(y, x % y); }
signed main() {
ios::sync_with_stdio(false);
int n, m;
cin >> n >> m;
for (register int i = 1; i <= m; i++) cin >> a[i].second >> a[i].first;
sort(a + 1, a + m + 1);
int answer = 0;
for (register int i = 1; n > 1 && i <= m; i++) {
int tn = gcd(n, a[i].second);
answer += (n - tn) * a[i].first;
n = tn;
}
if (n > 1)
cout << -1 << endl;
else
cout << answer << endl;
return 0;
}