ABC 210

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;
}
posted @ 2021-07-18 10:16  fhq_treap  阅读(55)  评论(0编辑  收藏  举报