机房测试8.23

题解之前

咕咕咕

因为教练不在,玩去了,好几天没有更新。%%%@wans鸽掉的几天这里有(妹子)

前几天谜题实验室推出了,每天晚上就和几个同学一起准备AC这上面的题,结果奴隶战OTK就花了好久才A。(祭奠天国的战歌)

%%% 辣个男人idy002 又来了。

prob

1447768-20180823155256102-2036731966.png

确实被我一眼秒杀的题,我却被我的傻逼做法秒杀了。

满足条件的一定只需要2道题。(n<=5时)

本来01状态压缩一下不就完事了,但是我脑子一抽,写了如下程序:


#include<cstdio>
#include<cctype>
#include<cstring>
#define FN "prob"

const int maxn=1e5+5;

int a[maxn],d[maxn];
int b[maxn],c[maxn];

namespace Baoli {
    void one(int num) {
        memset(b,0,sizeof(b));
        bool fl=false;
        for(int i=1;i<=num;i++) {
            char ch;while(!isdigit(ch=getchar()));
            b[i]=ch-'0';
            if(!b[i]) fl=true;
        }
        if(fl) printf("YES\n");
        else printf("NO\n");
        return ;
    }

    void two(int num) {
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        int _01=0,_00=0,_10=0;
        for(int i=1;i<=num;i++) {
            char ch;
            while(!isdigit(ch=getchar()));b[i]=ch-'0';
            while(!isdigit(ch=getchar()));c[i]=ch-'0';
            if(!b[i] && c[i]) _01++;
            if(!b[i] && !c[i]) _00++;
            if(b[i] && !c[i]) _10++;
        }
        if(_00) printf("YES\n");
        else if(_01 && _10) printf("YES\n");
        else printf("NO\n");
        return ;
    }

    void three(int num) {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        int _000=0,_001=0,_010=0,_011=0,_100=0,_101=0,_110=0;
        for(int i=1;i<=num;i++) {
                char ch;
                while(!isdigit(ch=getchar()));a[i]=ch-'0';
                while(!isdigit(ch=getchar()));b[i]=ch-'0';
                while(!isdigit(ch=getchar()));c[i]=ch-'0';
                if(!a[i] && !b[i] && !c[i]) ++_000;
                else if(!a[i] && !b[i] && c[i]) ++_001;
                else if(!a[i] && b[i] && !c[i]) ++_010;
                else if(!a[i] && b[i] && c[i]) ++_011;
                else if(a[i] && !b[i] && !c[i]) ++_100;
                else if(a[i] && !b[i] && c[i]) ++_101;
                else if(a[i] && b[i] && !c[i]) ++_110;
        }
        if(_000 || (_001 && (_010 || _100 || _110)) || (_010 && (_100 || _101)) || (_011 && _100))
            printf("YES\n");
        else printf("NO\n");
        return ;
    }
}

int main() {
    freopen(FN".in","r",stdin);
    freopen(FN".out","w",stdout);
    int T;scanf("%d",&T);
    while(T--) {
        int n,m;scanf("%d%d",&n,&m);
        if(m==1) Baoli::one(n);
        else if(m==2) Baoli::two(n);
        else if(m==3) Baoli::three(n);
        else {
            memset(a,0,sizeof(a));
            memset(b,0,sizeof(b));
            memset(c,0,sizeof(c));
            memset(d,0,sizeof(d));
            int _0000=0,_0001=0,_0010=0,_0011=0,_0100=0,_0101=0,_0110=0,_0111=0;
            int _1000=0,_1001=0,_1010=0,_1011=0,_1100=0,_1101=0,_1110=0;
            for(int i=1;i<=n;i++) {
                char ch;
                while(!isdigit(ch=getchar()));a[i]=ch-'0';
                while(!isdigit(ch=getchar()));b[i]=ch-'0';
                while(!isdigit(ch=getchar()));c[i]=ch-'0';
                while(!isdigit(ch=getchar()));d[i]=ch-'0';
                if(!a[i] && !b[i] && !c[i] && !d[i]) ++_0000;
                else if(!a[i] && !b[i] && !c[i] && d[i]) ++_0001;
                else if(!a[i] && !b[i] && c[i] && !d[i]) ++_0010;
                else if(!a[i] && !b[i] && c[i] && d[i]) ++_0011;
                else if(!a[i] && b[i] && !c[i] && !d[i]) ++_0100;
                else if(!a[i] && b[i] && !c[i] && d[i]) ++_0101;
                else if(!a[i] && b[i] && c[i] && !d[i]) ++_0110;
                else if(!a[i] && b[i] && c[i] && d[i]) ++_0111;
                else if(a[i] && !b[i] && !c[i] && !d[i]) ++_1000;
                else if(a[i] && !b[i] && !c[i] && d[i]) ++_1001;
                else if(a[i] && !b[i] && c[i] && !d[i]) ++_1010;
                else if(a[i] && !b[i] && c[i] && d[i]) ++_1011;
                else if(a[i] && b[i] && !c[i] && !d[i]) ++_1100;
                else if(a[i] && b[i] && !c[i] && d[i]) ++_1101;
                else if(a[i] && b[i] && c[i] && !d[i]) ++_1110;
            }
            if( _0000 || (_0001 && (_0010 || _0100 || _0110 || _1000 || _1010 || _1100 || _1110 ) ) ||
                         (_0010 && (_0100 || _0101 || _1000 || _1001 || _1100 || _1101 ) ) ||
                         (_0011 && (_0100 || _1000 || _1100 ) ) ||
                         (_0100 && (_1000 || _1001 || _1010 || _1011 ) ) || (_0111 && _1000) ||
                         (_0101 && (_1000 || _1010) ) || (_0110 && (_1000 || _1001) ) )
                printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}

清奇的做法,做法惊人的明显,std相当于简化了那些傻逼东西。
我真的不能理解,难道三点钟睡觉对考试状态影响那么大吗?
但是,这个程序一样完美AC。
(大爷还是你大爷)

std::如下

#include <bits/stdc++.h>
using namespace std;

int n, k;
int cnt[1<<4];

void yes() {
    printf("YES\n");
}
void no() {
    printf("NO\n");
}

int main() {
    freopen("prob.in", "r", stdin);
    freopen("prob.out", "w", stdout);
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &k);
        memset(cnt, 0, sizeof(cnt));
        for(int i = 1; i <= n; i++) {
            int s = 0;
            for(int j = 0; j < k; j++) {
                int v;
                scanf("%d", &v);
                if(v) s |= 1<<j;
            }
            cnt[s]++;
        }
        int U = (1<<k) - 1;
        for(int s1 = 0; s1 <= U; s1++)
            for(int s2 = 0; s2 <= U; s2++) {
                if(!cnt[s1] || !cnt[s2]) continue;
                if(!(s1 & s2)) {
                    yes();
                    goto NEXT;
                }
            }
        no();
NEXT:;
    }
}

pizza

1447768-20180823164711397-1927182038.png

贪心。
把一张张饼子看成一个个块,算一个delta,排一下序就知道哪个更适合吃哪一种饼子。
在delta正负分界的地方转换吃的饼子,中间这个块就两种都比较,哪个好吃吃哪个。

(其实是披萨)

有这么一个思路,写法千奇百怪。

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;

struct Stat {
    int d, s;
    Stat(){}
    Stat(int d, int s):d(d),s(s){}
};
bool operator<(const Stat &r, const Stat &s) {
    return r.d > s.d;
}

int n, S;
int s[N], a[N], b[N], d[N];
Stat stats[N];
long long pres[N];

long long cp(long long len) {
    long long ans = 0;
    for(int i = 1; i <= n; i++) {
        if(pres[i] <= len) {
            ans += (long long)stats[i].s * stats[i].d;
        } else {
            ans += (long long)(len - pres[i-1]) * stats[i].d;
            break;
        }
    }
    return ans;
}
long long calc(long long s, long long more) {
    vector<int> vc;
    for(int i = 1; i <= n; i++) {
        if(pres[i] >= s) {
            for(int j = 1; j <= pres[i] - s + 1 && more >= 1; j++) {
                vc.push_back(stats[i].d);
                more--;
            }
            for(int ii = i + 1; ii <= n && more >= 1; ii++)
                for(int j = 1; j <= stats[ii].s && more >= 1; j++) {
                    vc.push_back(stats[ii].d);
                    more--;
                }
            long long ans = 0;
            for(int t = 0; t < (int)vc.size(); t++) {
                if(vc[t] > 0) ans += vc[t];
            }
            return ans;
        }
    }
    return 0;
}
int main() {
    freopen("pizza.in", "r", stdin);
    freopen("pizza.out", "w", stdout);
    scanf("%d%d", &n, &S);
    long long sum = 0, ans = 0;
    for(int i = 1; i <= n; i++) {
        scanf("%d%d%d", s+i, a+i, b+i);
        sum += s[i];
        ans += (long long)b[i] * s[i];
        stats[i] = Stat(a[i] - b[i], s[i]);
    }
    sort(stats+1, stats+1+n);
    for(int i = 1; i <= n; i++) 
        pres[i] = pres[i-1] + stats[i].s;
    long long m = (sum + S - 1) / S;
    long long sub = 0;
    if(stats[n].d >= 0) {
        for(int i = 1; i <= n; i++)
            sub += (long long)stats[i].d * stats[i].s;
        ans += sub;
        printf("%lld\n", ans);
    } else {
        for(int i = 1; i <= n; i++) {
            if(stats[i].d < 0) {
                long long subans = ans + cp(pres[i-1] / S * S);
                long long more = S * m - sum;
                subans = max(subans, ans + cp(pres[i-1] / S * S + S - more) + calc(pres[i - 1] / S * S + S - more + 1, more));
                printf("%lld\n", subans);
                break;
            }
        }
    }
}

scream

1447768-20180823165308313-1492961326.png

我们比较容易想到的一个dp 是用dp[i][j] 前i 个数, 分成j 段, 最大的美味值. 转移为:
dp[i][j] = max dp[k -?1][j - 1] + c(k,j)
然后我们发现dp[i][j] 仅由dp[i][j -? 1] 转移过来, 我们把j 压掉, 然后用数据结构(线段树) 维护右边的max 值

#include <bits/stdc++.h>
using namespace std;

#define prev PREEVEV
const int N = 35000 + 10;
const int oo = 0x3f3f3f3f;

struct Node;
void modify(Node *nd, int lf, int rg, int L, int R, int delta);
struct Node {
    int vmax;
    int flag;
    Node *ls, *rs;
    void update() {
        vmax = max(ls->vmax, rs->vmax);
    }
    void pushdown(int lf, int rg) {
        if(flag) {
            int mid = (lf + rg) >> 1;
            modify(ls,lf,mid,lf,mid,flag);
            modify(rs,mid+1,rg,mid+1,rg,flag);
            flag = 0;
        }
    }
}pool[N*2], *tail, *root;

int n, m;
int aa[N], pos[N], prev[N];
int dp[2][N];
int cur = 1, prv = 0;

Node *build(int lf, int rg) {
    Node *nd = ++tail;
    nd->vmax = nd->flag = 0;
    if(lf == rg) {
        nd->vmax = dp[prv][lf];
    } else {
        int mid = (lf + rg) >> 1;
        nd->ls = build(lf, mid);
        nd->rs = build(mid+1, rg);
        nd->update();
    }
    return nd;
}
void modify(Node *nd, int lf, int rg, int L, int R, int delta) {
    if(L <= lf && rg <= R) {
        nd->vmax += delta;
        nd->flag += delta;
        return;
    }
    int mid = (lf + rg)>>1;
    nd->pushdown(lf,rg);
    if( L <= mid )
        modify(nd->ls, lf, mid, L, R, delta);
    if( R > mid )
        modify(nd->rs, mid+1, rg, L, R, delta);
    nd->update();

}
int query(Node *nd, int lf, int rg, int L, int R) {
    if(L <= lf && rg <= R)
        return nd->vmax;
    int mid = (lf + rg) >> 1;
    nd->pushdown(lf,rg);
    int rt = -oo;
    if( L <= mid )
        rt = max( rt, query(nd->ls, lf, mid, L, R) );
    if( R > mid )
        rt = max( rt, query(nd->rs,mid+1,rg,L,R) );
    return rt;
}
int main() {
    freopen("scream.in", "r", stdin);
    freopen("scream.out", "w", stdout);
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++)
        scanf("%d", aa + i);
    for(int i = 1; i <= n; i++) {
        prev[i] = pos[aa[i]];
        pos[aa[i]] = i;
    }
    
    for(int i = 1; i <= n; i++) 
        dp[prv][i] = dp[prv][i-1] + (prev[i] == 0);
    for(int k = 2; k <= m; k++) {
        tail = pool;
        root = build(1, n);
        for(int i = 1; i <= n; i++) {
            if(i < k )
                dp[cur][i] = -oo;
            else {
                modify(root, 1, n, max(prev[i],1), i - 1, +1);
                dp[cur][i] = query(root, 1, n, 1, i - 1);
            }
        }
        swap(prv, cur);
    }
    printf("%d\n", dp[prv][n]);
}

总结(讲垃圾话)

今天T1少写一行掉50分,充分证明晚睡觉的坏处。
T2 90分贪心就很迷。
T3 没时间写。

马上开学了,学校人越来越多,PS4完全不敢在党员工作室玩,真的难受。

明天又回家了,开学逼近,作业:1/100。
反正开学就要停课,应该没什么关系吧。

妥妥的200+就这么没了。

我的Rank3啊!

转载于:https://www.cnblogs.com/LoLiK/p/9524909.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值