Codeforces Round #264 (Div. 2)

题目: LINK

A。 水题,不多说。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std; 
#define INF 1000000000
//typedef __int64 LL; 
int n, s; 
int x, y; 
int main() 
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin); 
#endif 
    scanf("%d%d", &n, &s); 
    int ans = -INF; 
    for(int i = 1; i <= n; i++) {
        scanf("%d%d", &x, &y); 
        if(x > s) continue; 
        if(x == s && y) continue; 
        if(y == 0) ans = max(ans, 0); 
        else ans = max(ans, 100 - y); 
    }
    if(ans < 0) printf("-1\n"); 
    else printf("%d\n", ans); 
    
    return 0; 
}


B。 遍历一遍,就可以了.

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std; 
#define INF 1000000000
//typedef __int64 LL; 
#define N 100005
int hh[N], n; 
int main() 
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin); 
#endif // ONLINE_JUDGE
    scanf("%d", &n); 
    hh[0] = 0; 
    for(int i = 1; i<=n; i++) {
        scanf("%d", &hh[i]); 
    }
    int ans = 0; 
    int now = 0; 
    for(int i = 1; i<=n; i++){
        if(hh[i-1] >= hh[i]) {
            now += hh[i-1] - hh[i]; 
        }
        else {
            int tmp = hh[i] - hh[i-1]; 
            if(now >= tmp) {
                now -= tmp; 
            }
            else {
                ans += tmp - now; 
                now = 0; 
            }
        }
    }
    printf("%d\n", ans); 
    return 0; 
}


C. 可以看成DP吧,其实就是预处理出来每个点四个方向过来的总和。每个点的和为四个方向加起来

如果两个点,满足条件等价于两点的 横坐标之差,和纵坐标之差,有且仅有一个为奇数.

按照坐标的奇偶可以分为四类点,处理出来每一类的最值,和最值的坐标。之后 在满足条件的点的组合中取最大值就可以了. 注意这组数据就可以了

2

0 0

0 0

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
typedef __int64 LL;
#define N 2005
LL n;
LL num[N][N], dp1[N][N], dp2[N][N], dp3[N][N], dp4[N][N], dp[N][N];
LL ma[10];
struct node {
    int x, y;
}gg[10];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
    scanf("%I64d", &n);
    for(LL i = 1; i<=n; i++) {
        for(int j = 1; j <= n; j++) {
            scanf("%I64d", &num[i][j]);
        }
    }
    for(int i = 1; i<=n; i++) {
        for(int j = 1; j<=n; j++) {
            dp1[i][j] = dp1[i-1][j-1] + num[i][j];
        }
    }
    for(int i = 1; i<=n; i++) {
        for(int j = n; j>=1; j--) {
            dp2[i][j] = dp2[i-1][j+1] + num[i][j];
        }
    }
    for(int i = n; i>=1; i--) {
        for(int j = 1; j<=n; j++) {
            dp3[i][j] = dp3[i+1][j-1] + num[i][j];
        }
    }
    for(int i = n; i>=1; i--) {
        for(int j = n; j>=1; j--) {
            dp4[i][j] = dp4[i+1][j+1] + num[i][j];
        }
    }
    for(int i = 1; i<=n; i++) {
        for(int j = 1; j<= n; j++) {
            dp[i][j] = dp1[i][j] + dp2[i][j] + dp3[i][j] + dp4[i][j] - num[i][j] * 3;
            int ii = i&1;
            int jj = j&1;
            int s = (ii<<1) | jj;
            if(dp[i][j] >= ma[s]) {
                ma[s] = dp[i][j]; gg[s].x = i; gg[s].y = j;
            }
        }
    }
    LL ans = 0;
    int x1, y1, x2, y2;
    if(ma[0] + ma[1] >=ans) {
        ans = ma[0] + ma[1]; x1 = gg[0].x; y1 = gg[0].y;
        x2 = gg[1].x; y2 = gg[1].y;
    }
    if(ma[0] + ma[2] >= ans) {
        ans = ma[0] + ma[2]; x1 = gg[0].x; y1 = gg[0].y;
        x2 = gg[2].x; y2 = gg[2].y;
    }
    if(ma[3] + ma[1] >=ans) {
        ans = ma[3] + ma[1]; x1 = gg[3].x; y1 = gg[3].y;
        x2 = gg[1].x; y2 = gg[1].y;
    }
    if(ma[3] + ma[2] >=ans) {
        ans = ma[3] + ma[2]; x1 = gg[3].x; y1 = gg[3].y;
        x2 = gg[2].x; y2 = gg[2].y;
    }
    printf("%I64d\n", ans);
    printf("%d %d %d %d\n", x1, y1, x2, y2) ;
    return 0;
}



D. 给你k个长度为n的1~n的排列,求这k个的最长公共子序列. 发现 k 很小, 而且序列是n的排列, 注意这两个条件.
dp[i] 表示以第一个序列为参考,以第i个位置为终点的LCS的长度.
dp[i] = dp[j] + 1 ,if 第一个序列中num[j] num[i] (j<i)在所有序列中都满足num[i] 在 num[j]前面.
结果ans = max(dp[1~n]); 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std; 
#define INF 1000000000
#define N 7 
#define M 1010
int a[N][M], b[N][M], n, k, dp[M]; 
int main() 
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin); 
#endif 
    scanf("%d%d", &n, &k); 
    int tmp ; 
    for(int i = 1; i <= k; i++) {
        for(int j = 1; j<= n; j++) {
            scanf("%d", &tmp); a[i][j] = tmp; b[i][tmp] = j; 
        }
    }
    int ans = 0; 
    for(int i = 1; i <= n; i++) {
        dp[i] = 1; 
        for(int j = 1; j < i ; j++) {
            int flag = 0; 
            for(int ii = 2; ii <= k; ii ++) {
                if(b[ii][a[1][i]] < b[ii][a[1][j]]) flag = 1; 
                if(flag) continue;
            }
            if(flag) continue; 
            dp[i] = max(dp[j]+1, dp[i]); 
        }
        ans = max(ans, dp[i]); 
    }
    printf("%d\n", ans); 
    return 0; 
}


E. 给你n(1e5)个节点的有根数(1 is root) ,每个点有一个值,1e5个操作,第一种操作,求从根1到给定点v的路径上的满足gcd(val[v], val[xi]),xi是路径上的点,输出xi,如果有多个输出距离v最近的一个, 没有输出-1 .第二种操作是把某点的权值更改为一个新值.
第二种操作不会超过50.
CF测评机本来跑的就很快而且给了10s,直接裸着搞。
先遍历有根树,记录每个点的父亲,之后对于每个询问直接往上找就可以了。还有其他优美的解法?

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
//typedef __int64 LL;
#define N 100010
int hh[N], tot, n, q, val[N], par[N];
struct node {
    int u, v, next;
}edge[700000];
void init() {
    memset(hh, -1, sizeof(hh));
    tot = 0;
}
void add(int u, int v) {
    edge[tot].v = v; edge[tot].next = hh[u];
    hh[u] = tot ++;
}
int gcd(int x, int y) {
    if(!y) return x ;
    return gcd(y, x%y);
}
void dfs(int u, int last) {
    for(int i = hh[u]; i != -1; i = edge[i].next) {
        int v = edge[i].v;
        if(v == last) continue;
        par[v] = u;
        dfs(v, u);
    }
}
void sol(int u) {
    int tmp = par[u];
    int vv = val[u];
    while(tmp != 0) {
        if(gcd(val[tmp], vv) != 1) {
            printf("%d\n", tmp);    return ; 
        }
        tmp = par[tmp];
    }
    puts("-1");
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
    scanf("%d%d", &n, &q);
    for(int i = 1; i <= n ;i++)  scanf("%d", &val[i]); 
    init();
    int u, v;
    for(int i = 1; i < n; i++) {
        scanf("%d%d", &u, &v);
        add(u, v); add(v, u);
    }
    dfs(1, -1);
    while(q-- ) {
        int x, y, z;
        scanf("%d%d", &x, &y);
        if(x == 1) {
            sol(y);
        }
        else {
            scanf("%d", &z);
            val[y] = z;
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值