机房测试8.15

题解之前

纪念我亡去的CSDN
我的CSDN


买卖

题面

小明 找到了 n个商店,小明分别从第 1个走到第 n个。在每个商店中小明可以 :

买入 1个或 0个物品 A,若买入 1个消耗 ai;
卖出 1个或 0物品 A,若卖出 1个获得 bi。

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

对于10%的数据n≤10
对于40%的数据n≤1000
对于100%的数据n≤100000

解题法

贪就是了。

用一个堆来维护没买的物品。

到i时,如果i的卖出价比前面没买的物品里最便宜的要高,就买那个最便宜的,然后在这里买获得利润,弹出堆顶,更新答案。

但是,在这里卖出不一定最优,如果在之后卖了相当于损失了卖出价格那么多钱,再把卖出价推入堆中即可。

代码

#include <queue>
#include <cstdio>
#define _(d) while(d((c=getchar()-48)>=0))
int n,a[100002],t,x;long long u;
std::priority_queue<int>Q;
int get() {int c,x;_(!);x=c;_()x=x*10+c;return x;}
int main() 
{ freopen("buy.in","r",stdin);
  freopen("buy.out","w",stdout); 
for (t=n=get();t--;a[t]=get());
    for (;n--;)Q.push(-a[n]),(t=Q.top())>(x=-get())?Q.pop(),Q.push(x),u-=x-t:0;
    return !printf("%I64d",u);
}

鬼畜出题人的标程。
堪称丧病。

投资

问题描述

OIER 们投资了一 支股票 ,大家 都知道股票有赚赔,现给出 n天里 这支股 票的涨跌情况 ,都为 整数,涨为正跌负。 OIER 们想知道天数在 s到 e之间 的这只股票涨跌最大连续和 。

对于 30% 数据 ,1<=s<=e<=n<=100
对于 100% 数据 ,1<=s<=e<=n<=100000
对于 100% 数据, -10000<=ai<=10000

解题法

显然前缀和。

找每一个点(s~n)前边前缀和最小的那个来更新答案即可。

单调队列即可。

代码

#include<bits/stdc++.h>
#define FN "invest"

const int maxn=1e5+5;

int a[maxn];
int sum[maxn];
int q[maxn];

int main() {
    freopen(FN".in","r",stdin);
    freopen(FN".out","w",stdout);
    int n,s,e;
    scanf("%d%d%d",&n,&s,&e);
    for(int i=1;i<=n;i++) {
        scanf("%d",a+i);
        sum[i]=sum[i-1]+a[i];
    }
    int head=1,tail=1,ans=0;
    for(int i=s;i<=n;i++) {
        while(head<tail && i-q[head]>e) head++;
        while(head<tail && sum[i-s]<sum[q[tail-1]]) tail--;
        q[tail++]=i-s;
        ans=std::max(ans,sum[i]-sum[q[head]]);
    }
    printf("%d",ans);
    return 0;
}

游戏

题目

艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了。拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛。所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训练好拉拉队有多么的重要。拉拉队的选拔工作已经结束,在雨荨和校长的挑选下,n位集优秀的身材、舞技于一体的美女从众多报名的女生中脱颖而出。这些女生将随着篮球队的小伙子们一起,和对手抗衡,为艾利斯顿篮球队加油助威。一个阳光明媚的早晨,雨荨带领拉拉队的队员们开始了排练。n个女生从左到右排成一行,每个人手中都举了一个写有26个小写字母中的某一个的牌子,在比赛的时候挥舞,为小伙子们呐喊、加油。雨荨发现,如果连续的一段女生,有奇数个,并且他们手中的牌子所写的字母,从左到右和从右到左读起来一样,那么这一段女生就被称作和谐小群体。现在雨荨想找出所有和谐小群体,并且按照女生的个数降序排序之后,前K个和谐小群体的女生个数的乘积是多少。由于答案可能很大,雨荨只要你告诉她,答案除以19930726的余数是多少就行了。

n<=1,000,000
k<=1,000,000,000,000

解题法

这个manacher真的够裸。

(可问题是我完全没拍过板子)

其实二分长度Hash也可以AC

最后部分快速幂即可。

代码

manacher

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1000010
using namespace std;
int n;
long long k;
char c[N],s[N<<1];
int p[N<<1];
int A[N];
void manacher()
{
    int i,j;
    for(i=1;i<=n;i++)
    {
        s[2*i]=c[i];
        s[2*i-1]='#';
    }
    s[2*n+1]='#';
    s[0]='$';s[2*n+2]='&';
    int maxn=0,maxb=0;
    for(i=1;i<=2*n;i++)
    {
        if(i<maxn) p[i]=min(maxn-i,p[2*maxb-i]);
        else p[i]=0;
        while(s[i+p[i]+1]==s[i-p[i]-1]) p[i]++;
        if(i+p[i]>maxn)
        {
            maxn=i+p[i];
            maxb=i;
        }
    }
    for(i=2;i<=2*n;i+=2)
    A[p[i]]++;
}
int mod=19930726;
long long ksm(long long d,long long c)
{
    long long ret=1;
    while(c)
    {
        if(c&1) ret=ret*d%mod;
        d=d*d%mod;c/=2;
    }
    return ret;
}
int main()
{
	freopen("rehearse.in","r",stdin);
	freopen("rehearse.out","w",stdout);
    scanf("%d%I64d",&n,&k);
    scanf("%s",c+1);
    manacher();
    long long ans=1,i;
    for(i=n;i>=1;i--)
    {
        if(A[i]>=k)
        {
            (ans*=ksm(i,k))%=mod;
            break;
        }
        else
        {
            (ans*=ksm(i,A[i]))%=mod;
            k-=A[i];
            A[i-2]+=A[i];
        }
    }
    if(i==0) puts("-1");
    else printf("%I64d",ans);
}

二分Hash (By pypyzjj)

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e6+5;
int mod=19930726;
int base=2333;
long long n,m;
int b[N],a[N];
int ha1[N],baba[N],ha2[N];
char s1[N];
long long mi(long long a,long long b)
{
	long long ans=1;
	for(;b;b>>=1,a=a*a%mod)
	   if(b&1) ans=ans*a%mod;
	return ans;
}
int check(int x,int len)
{
	int l=x-len+1;
	int r=x+len-1;
	if(ha1[x]-ha1[l-1]*baba[len]==ha2[x]-ha2[r+1]*baba[len])
	   return 1;
	return 0;
}
int main()
{
	freopen("rehearse.in","r",stdin);
	freopen("rehearse.out","w",stdout);	
	cin>>n>>m;
	cin>>s1;
	int cnt=1;
	a[1]=1;
    while(a[cnt]<n){
    	cnt++;
    	a[cnt]=cnt*2-1;
    }
    if(a[cnt]>n) cnt--;
    baba[0]=1;
    for(int i=1;i<=n;i++)
       baba[i]=baba[i-1]*base;
    for(int i=1;i<=n;i++)
       ha1[i]=ha1[i-1]*base+s1[i-1];
    for(int i=n;i>=1;i--)
       ha2[i]=ha2[i+1]*base+s1[i-1];
    for(int i=1;i<=n;i++)
    {
    	int l=1,r=cnt,pos=-1;
    	while(l<=r)
    	{
    		int mid=(l+r)/2;
    		int bj=(a[mid]+1)/2;
    		if(bj+i-1>n||i-bj+1<1)
    		    r=mid-1;
    		else if(check(i,bj))
    		{
    			pos=mid;
    			l=mid+1;
    		}
    		else r=mid-1;
    	}
    	b[pos]++;
    }
    long long yl=0,sl=0,ans=1;
    for(int i=cnt;i>=1;i--)
    {
    	yl+=b[i];
    	sl+=yl;
    }
    if(sl<m)
    {
    	printf("-1");
    	return 0;
    }
    yl=0;
    for(int i=cnt;i>=1&&m>0;i--)
    {
    	yl+=b[i];
    	if(m>=yl)
    	{
    	ans=ans*mi(2*i-1,yl)%mod;	
    	m-=yl;
    	}	  
    	else if(m<yl)
    	{
    		ans=ans*mi(2*i-1,m)%mod;
    		break;
    	}
    }
    cout<<ans;
    return 0;
}


总结(讲垃圾话)

今天崩了

Rank 10+

每道题都知道怎么写

但都写错了。

菜的抠脚。

再接再厉!

posted @ 2018-08-15 19:08  LoLiK  阅读(331)  评论(0编辑  收藏  举报