18.8.15 考试总结

买卖
【问题描述】 小明找到了n个商店 小明 分别从第1个走到第n个。

在每个商店中小明可以 :买入1个或0个物品A,若买入1个消耗 ai;

卖出1个或 0物品 A,若卖出 ,若卖出1个获得bi.

求小明在最后能获得的最大价值 。


【输入格式】
从文件buy.in 中输入数据。 第一行一个整数n。

第二行n个整数,表示ai。 第三行n个整数,表示bi。


【输出格式】
输出到 文件 buy.out .out中。

第一行一个整数n。 第二行n个整数,表示ai。 第三行n个整数,表示bi。

 

这道题我一开始的贪心是错误的忘记考虑反悔的情况 

后来发现这道题可以用网络流打暴力 可以狗四十分的

但是不知道为什么除了第一个点都re 难过

标程就是维护一个堆 每次走到一个i时的时候,我们就把i的买入价格推到堆里,

如果点 i的卖出价格比前面还没买物品里最便宜要高  那么我们买入个最便宜的,

然后在这卖出就可以获得利润 把堆顶弹出并更新答案 但是可能这样子配对并不是最优的

所以就把b也压进去 以便反悔(b[j] - a[s] = b[j] - b[i] + b[i] - a[s])

代码

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

typedef long long ll;
const int N = 1e7;
struct node {
    ll x;
    bool operator < (const node & a) const {
        return x > a.x;
    }
};
priority_queue<node>Q;
ll a[N],b[N],ans;
int n;

int main( ) {
    
    freopen("buy.in","r",stdin);
    freopen("buy.out","w",stdout);
    scanf("%d",& n);
    for(int i = 1;i <= n;i ++) scanf("%I64d",& a[i]);
    for(int i = 1;i <= n;i ++) scanf("%I64d",& b[i]);
    for(int i = 1;i <= n;i ++) {
        
        node u,s; s.x = a[i];
        Q.push(s);
        u = Q.top( );
        if(u.x <= b[i]) {
            ans += b[i] - u.x;
            if(! Q.empty( )) Q.pop( ); 
            node ss; ss.x = b[i]; Q.push(ss);
        }    
    }
    printf("%I64d",ans);
}

投资
【问题描述】
OIER们投资了一 支股票 大家都知道股票有赚赔,现给出 n天里这支股票的涨跌情况 ,

都为整数,涨为正 跌为负。

OIER 们想知道天数在s到e之间的这只股票涨跌最大连续和 。


【输入格式 】
从文件 invest.in中输入数据。 第一行有三个正整数 n、s和 e ,同上描述。 接下来有n行,每一个整数 ai ,组成数列的顺序不 可以变换。


【输出格式】
输出到文件invest.out中。输出长度在s和e之间连续的数列数的和的最大值。

 

做的时候用的滑动窗口 结果wa了60分 不如打暴力...。

正解是维护最大前缀和 对于一个起点来说合法的串是i +s~i + e

所以在这个区间内用线段树维护一个最大前缀和 再减去sum[i - 1]即可

代码

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

typedef long long ll;
const int N = 1e6 + 5;
ll ans,sum[N],f[4 * N];
int n,s,e,a[N],que[2 * N],head,tail;

void update(int o) {
    
    f[o] = max(f[2 * o],f[2 * o + 1]);
}

void build(int o,int l,int r) {
    
    if(l == r) {
        f[o] = sum[l];
        return ;
    }
    int mid = (l + r) >> 1;
    build(2 * o,l,mid);
    build(2 * o + 1,mid + 1,r);
    update(o);
}

ll query(int o,int l,int r,int L,int R) {
    
    if(l >= L && r <= R) return f[o];
    int mid = (l + r) >> 1;
    ll ans = -oo;
    if(L <= mid) ans = max(ans,query(2 * o,l,mid,L,R));
    if(mid < R) ans = max(ans,query(2 * o + 1,mid + 1,r,L,R));
    return ans;
}

int main( ) {
    
    freopen("invest.in","r",stdin);
    freopen("invest.out","w",stdout);
    scanf("%d%d%d",& n,& s,& e);
    for(int i = 0;i < 4 * N;i ++) f[i] = -oo;
    for(int i = 1;i <= n;i ++) {
        scanf("%d",& a[i]);
        sum[i] = sum[i - 1] + a[i];
    }
    ans = -oo;
    build(1,1,n);
    for(int i = 1;i <= n;i ++) {
        if(i + s - 1 > n) break;
        ll qq = query(1,1,n,i + s - 1,min(i + e - 1,n));
        ans = max(ans,qq - sum[i - 1]);
    }
    printf("%I64d",ans);
    return 0;
}

游戏
【问题描述】
艾利斯顿商学院篮球队要参加一年度的市比赛了。拉拉队是篮球比赛的一个看点,

好队往能帮助球增加士气赢得最终比赛。所以作为队长的楚雨荨同学知道,

帮助篮球训练好有多么重要。选拔工作已经结束, 在雨荨和校长挑选下n位集优秀的身材、

舞技于一体的美女从众多报名生中脱颖而出。这些将随着篮球队小伙子们一起,和对手抗衡,

为艾利斯顿篮球队加油助威。一个阳光明媚的早晨雨荨带领队员们开始了排练。

n个女生从左到右排成一行,每人手中都举了写 有 26 个小写字母中的某一牌子,

在比赛时候挥舞为伙们呐喊、加油。雨荨发现,

如果连续的一段女生有奇数个并且他们手中牌子所写字母,从左到右和读起来一样,

那么这段女生就被称作和谐小群体。现在雨荨想找出所有和谐小群体,

并且按照女生的个数降序排之后前K个和谐小群体的女生个数乘积是多少。由于答案可能很大,

雨荨只要你告诉她谐小群体的女生个数乘积是多少。由于答案可能很大,

雨荨只要你告诉她案除以 19930726 的余数是多少就行了。


【输入格式】
从文件rehearse .in 中输入 数据。
第一行为两个正整数 n和 K,代表的东西在题目描述中已经叙。接下来一 行为 n个字符,

代表从左到右女生拿的牌子上写母。


【输出格式】
输出到文件rehearse .out .out中。 输出一个整数,

代表题目描述中所写的乘积除以 19930726 的余数,如果总 的和谐小群体个数于 K,输出一个整数 -1。

 

考试的时候基本是把正解给弄出来了的 然而我没写过manacher 我就自己乱yy了一个

wa了好几个点 t了3个点 还有统计答案的时候不够优秀 

答题思路就是manacher + 差分树状数组 + 快速幂

代码

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

typedef long long ll;
const int N = 1e6 + 5;
const ll mod = 19930726;
int n,f[N],t[N],mi,cent = 0;
char s[N];
ll c[N],k;

int lowbit(int i) {
    
    return (i)&(-i);
}

void add(int pos,ll val) {
    
    while(pos <= n) {
        c[pos] += val;
        pos += lowbit(pos);
    }
}

ll query(int pos) {
    
    ll ans = 0;
    while(pos >= 1) {
        ans += c[pos];
        pos -= lowbit(pos);
    }
    return ans;
}

ll fast_pow(ll a,ll b) {
    
    ll ans = 1;
    for(;b;b >>= 1,a = (a * a) % mod)
        if(b & 1) ans = (ans * a) % mod;
    return ans; 
}

void manacher( ) {
    
    s[0] = '-'; s[n + 1] = '+';
    for(int i = 1;i <= n;i ++) {
        if(i <= mi)        f[i] = min(mi - i, f[cent * 2 - i]);
        else    f[i] = 0;
        while(s[i - f[i] - 1] == s[i + f[i] + 1])    f[i]++;
        if(i + f[i] > mi) {
            mi = i + f[i];
            cent = i;
        }
        add(1,1); add(1 + f[i] * 2 + 1,-1);
    }
}

void solve( ) {
    
    ll sum = 0,ans = 1;
    int st = n;
    if(st % 2 == 0) st --;
    for(int i = st;i >= 1;i -= 2) {
        ll num = query(i);
        if(sum + num >= k) {
            ans = ans * fast_pow(i,k - sum) % mod;
            sum = k;
            printf("%I64d",ans); break;
        }
        else {
            ans = ans * fast_pow(i,num) % mod;
            sum += num;
        }
    }
    if(sum < k) printf("-1");
}

int main( ) {
    
    freopen("rehearse.in","r",stdin);
    freopen("rehearse.out","w",stdout);
    scanf("%d%I64d",& n,& k);
    scanf("%s",s + 1);
    manacher( );
    solve( );
}

 

posted @ 2018-08-15 17:30  阿澈说他也想好好学习  阅读(290)  评论(0编辑  收藏  举报