码迷,mamicode.com
首页 > 其他好文 > 详细

YALIDAY3

时间:2018-12-13 22:42:00      阅读:315      评论:0      收藏:0      [点我收藏+]

标签:递增   [1]   main   getchar   size   错题   git   ios   ==   

目录

雅礼DAY2测试

时间安排

T1: 80分钟 T2: 100分钟 T3:120分钟

  • 第一题是个贪心题, 写完暴力和std打的对拍
  • 第二题是个结论题, 也写完了
  • 第三题打的30暴力
答题情况
  • T1:100 T2:100 T3:40

  • 今天第一次提交, 不知道要建立子文件夹, 导致没有成绩
  • 成绩是我线下自己测的

题目解析
T1
  • 实际上发现假如有两个相连的0, 那么就会对于两边分别做
  • 这样分成了狠毒哦块, 每块有两种决策, 直接改成1或者先用两次机会改成全1, 然后全改成0
  • 取min即可
T2
  • 发现类似于前缀的那个东西是可以优化的, 第一次min值是个V形线, 取min之后就是_/的样子, 之后若加入的点在前面min图像就会变成_/还有另外一种
    发现之后的加入都是形成一个下凸的东西, 想办法维护它,发现维护交点就可以了
T3
  • 结论是我们得到的序列一定是先单调递减然后单调递增的
  • 然后就找到所有这样的合法排列, 将数字排序后从小到大填入并且考虑性质就好了
代码实现
T1
正解
/*
题面牛鬼蛇神??
还有这数据是什么鬼
大概是个划分形的 贪心QWQ

连续的一段1显然可以用两次制造出来(只有连续一个的1除外)
然后 贪心???
先打个n^2暴力吧

是不是我理解错题目了

算了不管了QAQ
转移是单调的吧 ?? 弄个试试  咋弄啊 *(Y*……&*

好像连续两个0不行

*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#define M 1000100
#define ll long long
using namespace std;

int read() {
    int nm = 0, f = 1;
    char c = getchar();
    for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    return nm * f;
}

char s[M];
int a[M], sum[M], n, f[M], sta[M], tp;
int main() {
    freopen("twobit.in", "r", stdin), freopen("twobit.out", "w", stdout);
    n = read();
    scanf("%s", s + 1);
    for(int i = 1; i <= n; i++) a[i] = s[n - i + 1] - '0', sum[i] = sum[i - 1] + (a[i] == 0);
    if(n <= 300) {
        f[0] = 0;
        for(int i = 1; i <= n; i++) {
            f[i] = f[i - 1] + a[i];
            for(int j = 1; j < i; j++) f[i] = min(f[i], f[j - 1] + 2 + sum[i] - sum[j - 1]);
        }
        cout << f[n] << "\n";
    } else {
        int ans = n - sum[n], tmp = 0;
        int now = 1;
        while(1) {
            while(!a[now] && now <= n) now++;
            tp = 0;
            if(now > n) break;
            while(a[now] || a[now + 1]) sta[++tp] = now++;
            tmp += min(tp - (sum[sta[tp]] - sum[sta[1] - 1]), 2 + sum[sta[tp]] - sum[sta[1] - 1]);
        }
        ans = min(ans, tmp);
        cout << ans << "\n";
    }
    return 0;
}

T2
正解
/*
暴力n^2

发现类似于前缀的那个东西是可以优化的, 第一次min值是个V形线, 取min之后就是_/的样子, 之后若加入的点在前面min图像就会变成\_/还有另外一种
发现之后的加入都是形成一个下凸的东西, 想办法维护它,发现维护交点就可以了 



*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#define M 1000010
#define N 1010
#define ll long long
using namespace std;

int read() {
    int nm = 0, f = 1;
    char c = getchar();
    for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    return nm * f;
}

int f[N];
int n, a[M], maxx, minn[N];
int ab(int x) {
    return x > 0 ? x : -x;
}
ll ans;
priority_queue<int, vector<int>, greater<int> > que;

int main() {
    freopen("lis.in", "r", stdin);freopen("lis.out", "w", stdout);
    n = read();
    for(int i = 1; i <= n; i++) a[i] = read(), maxx = max(maxx, a[i]);
    if(n <= 1000 && maxx <= 1000) {
        memset(f, 0x3e, sizeof(f));
        for(int i = 0; i <= maxx; i++) f[i] = ab(i - a[1]);
        for(int i = 2; i <= n; i++) {
            memset(minn, 0x3e, sizeof(minn));
            for(int j = maxx; j >= 0; j--) minn[j] = min(minn[j + 1], f[j]);
            memset(f, 0x3e, sizeof(f));
            for(int j = 0; j <= maxx; j++) f[j] = minn[j] + ab(a[i] - j);
        }
        int ans = 0x3e3e3e3e;
        for(int i = 0; i <= maxx; i++) ans = min(ans, f[i]);
        cout << ans << "\n";
        return 0;
    } else {
        for(int i = 1; i <= n; i++) {
            que.push(a[i]);
            if(a[i] > que.top()) {
                ans += a[i] - que.top();
                que.pop();
                que.push(a[i]);
            }
        }
        cout << ans << "\n";
    }
    return 0;
}


T3
40暴力
/*
只能打暴力么QAQ
好像能加个记忆化 OVO
 仅此而已了, 离散出所有的差, 然后按照大小分类 , 实际上只有n + 1类, 然后记忆化dfs一下 (n + 1) (2 ^ n)
能不能把状态压缩的那个状态去掉呢??
md 题面除以2需要自己补充??? zzzzzzzzzz
好像不能只记录差, 离散化不了
弃疗了
话说记忆化有啥用??? 枚举全排列不就完了

好的其实这个题目题面写错了

要求出所有的相当于        
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#define ll long long
#define M 66
using namespace std;

int read() {
    int nm = 0, f = 1;
    char c = getchar();
    for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    return nm * f;
}
const int mod = 1000000007;
int note[66];
int sta[111111], tp;
int a[M], n;
int f[22][1 << 20];
bool vis[22][1 << 20];
bool gt[99];
int b[M];
void add(int &x, int y) {
    x += y;
    x -= x >= mod ? mod : 0;
}
int mp[1111111];
int  dfs(int now, int bt) {
    if(now == n) return 1;
    if(now >= 2) {
        int op = 2 * b[now - 1] - b[now - 2];
        int zz = mp[op + 100000];
        f[zz][bt] = 0;
        for(int i = zz; i <= n; i++) {
            if(!gt[i]) {
                gt[i] = true;
                b[now] = a[i];
                add(f[zz][bt], dfs(now + 1, bt | (1 << (i - 1))));
                gt[i] = false;
            }
        }
        return f[zz][bt];
    } else {
        int ans = 0;
        for(int i = 1; i <= n; i++) {
            if(!gt[i]) {
                gt[i] = true;
                b[now] = a[i];
                add(ans, dfs(now + 1, bt | (1 << (i - 1))));
                gt[i] = false;
            }
        }
        return ans;
    }
}

int main() {
    //freopen("squence.in", "r", stdin), freopen("squence.out", "w", stdout);
    n = read();
    if(n > 20) {
        cout << "20020216";
        return 0;
    }
    if(n <= 2) {
        cout << n << "\n";
        return 0;
    }
    else
    for( 
    for(int i = 1; i <= n; i++) a[i] = read();
    sort(a + 1, a + n + 1);
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= n; j++) {
            if(i == j) continue;
            sta[++tp] = 2 * a[i] - a[j];
        }
    }
    a[n + 1] = 0x3e3e3e3e;
    sort(sta + 1, sta + tp + 1);
    for(int i = 1; i <= tp; i++) {
        for(int j = 1; j <= n + 1; j++) {
            if(a[j] >= sta[i]) {
                mp[sta[i] + 100000] = j;
                break;
            }
        }
    }
    cout << dfs(0, 0) << "\n";
    return 0;
}
/*
3
1 2 0

*/
正解
/*
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#define M 66
#define ll long long
using namespace std;
const int mod = 1000000007;
ll read() {
    ll nm = 0, f = 1;
    char c = getchar();
    for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    return nm * f;
}

void add(int &x, int y) {
    x += y;
    x -= x >= mod ? mod : 0;
}

int f[M][M][M][M];
int a[M], n, ans;

int main() {
    //freopen(".in", "r", stdin), freopen(".out", "w", stdout);
    n = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    sort(a + 1, a + n + 1);
    int now = 0, fac = 1;
    while(a[now + 1] == a[1]) now++, fac = 1ll * fac * now % mod;
    f[0][now][0][now] = 1;
    for(int i = 0; i <= n; i++)
        for(int j = i; j <= n; j++)
            for(int k = 0; k <= n; k++)
                for(int l = k; l <= n; l++) {
                    if(!f[i][j][k][l]) continue;
                    int now = max(i, max(j, max(k, l))) + 1;
                    if(now == n + 1) add(ans, f[i][j][k][l]);
                    else {
                        if(i == 0 || a[now] - a[j] >= a[j] - a[i]) add(f[j][now][k][l], f[i][j][k][l]);
                        if(k == 0 || a[now] - a[l] >= a[l] - a[k]) add(f[i][j][l][now], f[i][j][k][l]);
                    }
                }
    cout << 1ll * ans * fac % mod << "\n";
    return 0;
}

YALIDAY3

标签:递增   [1]   main   getchar   size   错题   git   ios   ==   

原文地址:https://www.cnblogs.com/luoyibujue/p/10116869.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!