2017 ACM/ICPC Asia Regional Shenyang Online

1002

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
const int MOD = 1e9 + 7;
int main() {
    LL m,k;
    while(~scanf("%lld%lld",&m,&k))
        printf("%lld\n",(m-k+1)*k);
    return 0;
}


1004

题意:问删除准确的k个数后,所剩下的数组成的序列能否成为非递减序列或非递增序列

思路:求一下序列非递减和非递增序列的长度即可

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b)    memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 2e5 + 10;
const int INF = 1e9 + 10;
int num[qq];
int p[qq];
int n, k;

int main(){
    int t;    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", num + i);
        }
        int len = 0;
        for(int i = 1; i <= n; ++i) {
            if(len == 0) {
                p[len++] = num[i];
            } else if(num[i] >= p[len - 1]) {
                p[len++] = num[i];
            } else {
                int id = lower_bound(p, p + len, num[i]) - p;
                p[id] = num[i];
            }
        }
        if(n - len <= k) {
            puts("A is a magic array.");
            continue;
        }
        len = 0;
        for(int i = n; i >= 1; --i) {
            if(len == 0) {
                p[len++] = num[i];
            } else if(num[i] <= p[len - 1]) {
                p[len++] = num[i];
            } else {
                int id = lower_bound(p, p + len, num[i]) - p;
                p[id] = num[i];
            }
        }
        if(n - len <= k) {
            puts("A is a magic array.");
            continue;
        }
        puts("A is not a magic array.");
    }
    return 0;
}


1005

题意:给你一个数字k,代表你可以使用k个斐波那契数组成和,求不能组成的最小和

思路:推了一下发现结果就是求 2 * k + 3项的斐波那契数 减1

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b)    memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 998244353;
const int qq = 2e5 + 10;
const int INF = 1e9 + 10;
LL k;
struct Mar {
    LL mar[2][2];
    Mar operator * (const Mar &w) const {
        Mar tmp;
        mst(tmp.mar, 0);
        for(int i = 0; i < 2; ++i) {
            for(int j = 0; j < 2; ++j) {
                for(int k = 0; k < 2; ++k) {
                    tmp.mar[i][j] += (mar[i][k] * w.mar[k][j]);
                    tmp.mar[i][j] %= MOD;
                }
            }
        }
        return tmp;
    }
}ans, tmp;
Mar QuickPow(LL n) {
    mst(tmp.mar, 0);
    tmp.mar[0][0] = tmp.mar[1][1] = 1;
    while(n > 0) {
        if(n & 1)    tmp = tmp * ans;
        ans = ans * ans;
        n >>= 1;
    }
    return tmp;
}

int main(){
    while(scanf("%lld", &k) != EOF) {
        LL n = 2 * k + 3;
        ans.mar[0][0] = ans.mar[0][1] = ans.mar[1][0] = 1;
        ans.mar[1][1] = 0;
        ans = QuickPow(n);
        printf("%lld\n", ans.mar[0][1] - 1);
    }    
    return 0;
}


1008

题意:n个结点,n-1条边,保证是一棵树,然后给你每个结点买书和卖书的价值(只能买一本书和卖一本书,可以同时在一个地方买书卖书),问你最多可以赚多少钱,你可以从任意结点出发,赚的钱 = 卖书价格 - 买书价格 - 两地之间的距离

思路:树形dp,tive[i] 和 dis[i]表示以i为买书或卖书地点能赚的最多的钱时所选择的另外一个城市的价格以及距离,然后从下向上更新即可

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b)    memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e5 + 10;
const int INF = 1e9 + 10;
int ans[qq], price[qq], tive[qq], dis[qq];
int n;
vector<int> G[qq], f[qq];
void Init() {
    for(int i = 1; i <= n; ++i) {
        G[i].clear();
        f[i].clear();
    }
}
void Dfs(int u, int fa) {
    int sz = G[u].size();
    int maxn = 0, p, d;
    for(int i = 0; i < sz; ++i) {
        int v = G[u][i];
        if(v == fa)    continue;
        Dfs(v, u);
        if(dis[v] != 0 && abs(price[u] - tive[v]) - (dis[v] + f[u][i]) > maxn) {
            maxn = abs(price[u] - tive[v]) - (dis[v] + f[u][i]);
            p = tive[v];
            d = dis[v];
        }
        if(abs(price[u] - price[v]) - f[u][i] > maxn) {
            maxn = abs(price[u] - price[v]) - f[u][i];
            p = price[v];
            d = f[u][i];
        }
    }
    if(maxn == 0) {
        p = price[u];
        d = 0;
    }
    ans[u] = maxn;
    tive[u] = p;
    dis[u] = d;
}

int main(){
    int t;    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", price + i);
        }
        for(int x, y, z, i = 1; i < n; ++i) {
            scanf("%d%d%d", &x, &y, &z);
            G[x].pb(y), f[x].pb(z);
            G[y].pb(x), f[y].pb(z);
        }
        Dfs(1, -1);
        int maxn = 0;
        for(int i = 1; i <= n; ++i) {
            maxn = max(maxn, ans[i]);
//            printf("%d %d %d\n", ans[i], tive[i], dis[i]);
        }
        printf("%d\n", maxn);
        Init();
    }
    return 0;
}


1012

题意:给出一个n,然后a序列有n个数,b序列有n个数,你可以操作,同时将序列a和序列b中最前面的数移动到最后面, 移动后你可以求一个和,(a[1] - b[1]) + ... + (a[k] - b[k]),此时的和第一次小于0,要求a[1] + a[2] + ... a[k]最大,问你至少要操作几次

思路:让两个序列形成一条链,然后尺取

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e6 + 10;
const int INF = 1e9 + 10;
int a[2 * qq], b[2 * qq], n;

int main(){
	while(scanf("%d", &n) != EOF) {
		for(int i = 1; i <= n; ++i) {
			scanf("%d", a + i);
		}
		for(int i = n + 1; i <= 2 * n; ++i) {
			a[i] = a[i - n];
		}
		for(int i = 1; i <= n; ++i) {
			scanf("%d", b + i);
		}
		for(int i = n + 1; i <= 2 * n; ++i) {
			b[i] = b[i - n];
		}
		int l = 1;
		int sum = 0, maxn = 0, card = 0;
		int id = 1;
		for(int i = 1; i <= 2 * n; ++i) {
			sum += (a[i] - b[i]);
			card += a[i];
			while(sum < 0 && l <= i) {
				sum -= (a[l] - b[l]);
				card -= a[l];
				l++;
			}
			if(l > i) {
				sum = 0;
				card = 0;
			}
			if(card > maxn) {
				id = l - 1;
				maxn = card;
			}
//			printf("%d\n", maxn);
		}
		printf("%d\n", id);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值