codeforces——1016

Table of Contents

codeforces----1016

codeforces----1016A

codeforces----1016B

codeforces----1016C

codeforces----1016D

codeforces----1016E


codeforces----1016

codeforces----1016A

http://codeforces.com/problemset/problem/1016/A

#include<iostream>
using namespace std;
int main() {
    int n, m;
    while ( cin >> n >> m ) {
        int now = 0, temp;
        while ( n-- ) {
            cin >> temp;
            now += temp;
            cout << now / m << ' ';
            now = now % m;
        }
        cout<<endl;
    }
    return 0;
}

 

codeforces----1016B

问子串在母串中出现的次数

kmp查询

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int next[1008];
vector<int>ans;
void setnext ( char *a ) {
    int i = 0, j = -1;
    next[0] = -1;
    while ( a[i] ) {
        if ( j == -1 || a[i] == a[j] ) next[++i] = ++j;
        else j = next[j];
    }
}
void kmp ( char *a, char *b ) {
    int i = 0, j = 0, m = strlen ( b );
    while ( a[i] ) {
        if ( j == -1 || a[i] == b[j] )++i, ++j;
        else j = next[j];
        if ( j == m ) {
            ans.push_back ( i );
            j = next[j];
        }
    }
}
int main() {
    int n, m, k;
    while ( cin >> n >> m >> k ) {
        char s1[1008], s2[1008];
        cin >> s1 >> s2;
        ans.clear();
        setnext ( s2 );
        kmp ( s1, s2 );
        while ( k-- ) {
            int temp1, temp2, a = 0;
            cin >> temp1 >> temp2;
            for ( vector<int>::iterator it = ans.begin(); it != ans.end(); it++ )
                if ( temp1 <= *it && temp1 <= *it - m + 1 && *it <= temp2 && *it + 1 - m <= temp2 )
                    a++;
            cout << a << endl;
        }
    }
    return 0;
}

 

codeforces----1016C

http://codeforces.com/problemset/problem/1016/C

从左上角出发的一条路径(a1~~an),求最大的1*a1+2*a2+...+n*an

dp的记忆化数组(我这个写的不好。)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define f(a) ((a)==0?1:0)
long long in[2][300008], n;
long long a[2][300008], ra[2][300008];
long long b[2][300008], rb[2][300008];
long long func1 ( int x, int y, int val ) {
    if ( y == n ) return val * in[x][y] + ( val + 1 ) * in[f ( x )][y];
    long long fin = b[x][n] - b[x][y - 1] + ( a[x][n] - a[x][y - 1] ) * ( val - y ) ;
    fin += rb[f ( x )][y] + ra[f ( x )][y] * ( val + n - y );
    return max ( fin, in[f ( x )][y] * ( val + 1 ) + in[x][y] *val  + func1 ( f ( x ), y + 1, val + 2 ) );
}
int main() {
    while ( cin >> n ) {
        for ( int i = 0; i < 2; i++ )
            for ( int j = 1; j <= n; j++ )
                scanf ( "%d", &in[i][j] );
        a[0][0] = a[1][0] = 0;
        for ( int k = 0; k < 2; k++ )
            for ( int i = 1; i <= n; i++ )
                a[k][i] = in[k][i] + a[k][i - 1];
        ra[0][n + 1] = ra[1][n + 1] = 0;
        for ( int k = 0; k < 2; k++ )
            for ( int i = n; i >= 1; i-- )
                ra[k][i] = in[k][i] + ra[k][i + 1];
        b[0][0] = b[1][0] = 0;
        for ( int k = 0; k < 2; k++ )
            for ( int i = 1; i <= n; i++ )
                b[k][i] = i * in[k][i] + b[k][i - 1];
        rb[0][n + 1] = rb[1][n + 1] = 0;
        for ( int k = 0; k < 2; k++ )
            for ( int i = n; i >= 1; i-- )
                rb[k][i] = ( n - i + 1 ) * in[k][i] + rb[k][i + 1];
        printf ( "%I64d\n", func1 ( 0, 1, 0 ) );
    }
    return 0;
}

 

codeforces----1016D

http://codeforces.com/problemset/problem/1016/D

给你一个矩阵的每行每列的异或值,如果存在就构造一个。

首先对所有的值异或一次,因为矩阵的每个点都会被访问两次,因此异或值必须为0

构造矩阵时我们靠任何值异或0都是其本身的特点,只构造最后一行一列,显然除了右下角的都直接构造。

类似于这样           

0  0  0  0  0  0  0  0  0  a1
0  0  0  0  0  0  0  0  0  a2
0  0  0  0  0  0  0  0  0  a3
0  0  0  0  0  0  0  0  0  a4
0  0  0  0  0  0  0  0  0  a5
0  0  0  0  0  0  0  0  0  a6
0  0  0  0  0  0  0  0  0  a7
0  0  0  0  0  0  0  0  0  a8
0  0  0  0  0  0  0  0  0  a9
b1 b2 b3 b4 b5 b6 b7 b8 b9 t

我们要知道      a1^a2^...^an-1^t=bn 因此 t=a1^a2^...an-1^bn。显然有关数组b的同理。因此只要选一个方案求 t 即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main() {
    int n, m;
    while ( cin >> n >> m ) {
        int in[2][108], temp = 0;
        for ( int i = 0; i < n; i++ )
            cin >> in[0][i], temp = temp ^ in[0][i];
        for ( int i = 0; i < m; i++ )
            cin >> in[1][i], temp = temp ^ in[1][i];
        if ( temp != 0 ) {
            cout << "NO" << endl;
            continue;
        } else cout << "YES" << endl;
        for ( int i = 0; i < n; i++ )
            for ( int j = 0; j < m; j++ )
                if ( j == m - 1 && i == n - 1 ) {
                    temp = in[0][n - 1];
                    for ( int k = 0; k < m - 1; k++ )
                        temp = temp ^ in[1][k];
                    cout << temp << endl;
                } else if ( j == m - 1 ) cout << in[0][i] << endl;
                else if ( i == n - 1 ) cout << in[1][j] << ' ';
                else cout << "0 ";
    }
    return 0;
}

codeforces----1016E

http://codeforces.com/problemset/problem/1016/E

一个光源的移动区间,多个挡板,多次查询,问查询点在阴影范围的时间。

数据很大,思路是进行线段树优化。

因此,藉由光源和查询点,由相似性 覆盖到挡板区间,通过判断挡板遮盖的比例来判断时间

线段树进行时间优化。

ps.我不知道输入选择浮点型,我的代码非浮点型 Wrong answer on test 3 ,我看输入写的都是整形常量啊。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
double Left, Right;
class AP {
public:
    double l, r, val;
} tree[800008];
void pushup ( int i ) {
    tree[i].l = tree[2 * i].l;
    tree[i].r = tree[2 * i + 1].r;
    tree[i].val = tree[2 * i].val + tree[2 * i + 1].val;
}
void build ( int i, int L, int R ) {
    if ( L == R ) {
        scanf ( "%lf%lf", &tree[i].l, &tree[i].r );
        tree[i].val = tree[i].r - tree[i].l;
        return;
    }
    int mid = ( L + R ) / 2;
    build ( 2 * i, L, mid );
    build ( 2 * i + 1, mid + 1, R );
    pushup ( i );
}
double sum ( int i, int L, int R ) {
    if ( Left <= tree[i].l && tree[i].r <= Right ) return tree[i].val;
    if ( L == R )
        if ( Right < tree[i].l || tree[i].r < Left ) return 0;
        else return min ( Right, tree[i].r ) - max ( Left, tree[i].l );
    int mid = ( L + R ) / 2;
    double ans = 0;
    if ( Left <= tree[2 * i].r && Right >= tree[2 * i].l ) ans += sum ( 2 * i, L, mid );
    if ( Left <= tree[2 * i + 1].r && Right >= tree[2 * i + 1].l ) ans += sum ( 2 * i + 1, mid + 1, R );
    return ans;
}

double point[200003][2];
int main() {
    int sy, a, b;
    while ( ~scanf ( "%d%d%d", &sy, &a, &b ) ) {
        int n, m;
        sy = -sy;
        scanf ( "%d", &n );
        build ( 1, 1, n );
        scanf ( "%d", &m );
        for ( int i = 0; i < m; i++ )
            scanf ( "%lf%lf", &point[i][0], &point[i][1] );
        for ( int i = 0; i < m; i++ ) {
            Left = 1.0 * ( sy * point[i][0] + point[i][1] * a ) / ( sy + point[i][1] );
            Right = 1.0 * ( sy * point[i][0] + point[i][1] * b ) / ( sy + point[i][1] );
            printf ( "%.6lf\n", sum ( 1, 1, n ) / ( Right - Left ) * ( b - a ) );
        }
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值