2017 ACM/ICPC Asia Regional Shenyang Online

1002

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#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 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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair
#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;
}


你可能感兴趣的:(线上比赛)