弱鸡儿长乐爆零旅Day3

T1奶牛晒衣服

【问题描述】

    在熊大妈英明的带领下,时针和他的同伴生下了许多牛宝宝。熊大妈决定给每个宝宝都穿上可爱的婴儿装。于是,为牛宝宝洗晒衣服就成了很不爽的事情。

    圣人王担负起了这个重任。洗完衣服后,你就要弄干衣服。衣服在自然条件下用1的时间可以晒干A点湿度。抠门的熊大妈买了1台烘衣机。使用烘衣机可以让你用1的时间使1件衣服除开自然晒干的A点湿度外,还可烘干B点湿度,但在1的时间内只能对1件衣服使用。

    N件的衣服因为种种原因而不一样湿,现在告诉你每件衣服的湿度,要你求出弄干所有衣服的最少时间(湿度为0为干)。

【输入格式】

    第一行N,A,B,接下来N行,每行一个数,表示衣服的湿度(1<=湿度,A,B<=500000,1<=N<=500000)。

【输出格式】

    一行,最少时间。

【输入样例】Dry.in

    3 2 1

    1

    2

    3

【输出样例】Dry.out

    1

样例解析】

    第1个时间内,用机器处理第3件衣服,此外,所有衣服自然晒干2。花费1时间全部弄干。

优先队列做法

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
priority_queue<int>q;
inline int read()
{
    int f=0;
    char ch=getchar();
    while(ch>'9' || ch<'0')
        ch=getchar();
    while(ch>='0' && ch<='9'){
        f=f*10+ch-'0';
        ch=getchar();
    }
    return f;
}
int n,a,b;
int main()
{
    freopen("Dry.in","r",stdin);
    freopen("Dry.out","w",stdout);
    n=read();a=read();b=read();
    for(int i=1;i<=n;i++){
        int x=read();
        q.push(x);
    }
    int i;
    for(i=0;;++i){
        int x=q.top();q.pop();
        if(x-a*i<=0) break;
        else if(x-b>0)q.push(x-b);
    }
    printf("%d",i);
    return 0;
}

O(n)算法 from cjt(长乐某巨佬

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
inline int read()
{
    int f=0;
    char ch=getchar();
    while(ch>'9' || ch<'0')
        ch=getchar();
    while(ch>='0' && ch<='9'){
        f=f*10+ch-'0';
        ch=getchar();
    }
    return f;
}
int n,a,b;
int cnt[500010];
int main()
{
    int mx=-1;
    n=read();a=read();b=read();
    for(int i=1;i<=n;i++){
        int x=read();
        cnt[x]++;
        mx=max(mx,x);
    }
    int t=0;
    while(t*a<mx){
        t++;
        if(mx-b>0)cnt[mx-b]++;
        cnt[mx]--;
        while(!cnt[mx])mx--;
    }
    printf("%d",t);
    return 0;
}

 

T2解密文本

【问题描述】

    已知英语中26个字母出现的概率p[0],p[1]……,p[25](它们的和为1),分别表示’a’, ‘b’,‘c’……出现的概率(大写字母和小写字母被认为是一样的)。

    现在有一个加密过的文件,加密方法是将原文件中的每一个字母进行相同的变换,其他的字符不变,变换的方法如下:

    如果将a到z编号为0到25,那么字母i将被替换成(i+k) mod 26,0<=k<26。原来是大写的字母,仍然是大写,原来是小写的字母仍然是小写。

    但是你并不知道k的值,所以只好枚举。因为知道26个字母出现的频率,所以你可以选择一个尽量好的k,使得频率的方差和最小,方差和定义如下:

    假设你枚举的k还原出来的原文件中的26个字母出现的概率为x[0], x[1], ……, x[25],那么方差和为:(p[0]-x[0])^2 + (p[1]-x[1])^2 + …… + (p[25]-x[25])^2

    如果有两个相同的k一样好,那么选较小的k

    最后输出解密出的原文件。

【输入格式】

    前26行分别是26个字母出现的概率。

    接下来是一个只含有26个大小写字母和空格,换行符,标点符号,阿拉伯数字等的文本。

【输出格式】

    解密过的文本。

【输入样例】

0.109375

0.000000

0.062500

0.015625

0.109375

0.015625

0.015625

0.000000

0.062500

0.015625

0.000000

0.078125

0.062500

0.062500

0.093750

0.015625

0.015625

0.031250

0.046875

0.046875

0.046875

0.000000

0.000000

0.000000

0.093750

0.000000

L dp Ol Bxtldq, ru brx fdq fdoo ph VsdfhIobhu.

L dp jodg wr vhh brx.

Hqmrb pb frqwhvw.

【输出样例】

I am Li Yuqian, or you can call me SpaceFlyer.

I am glad to see you.

Enjoy my contest.

分析:处理数据 枚举 完事

-----------------------------------------------------xjh:T2不是很简单吗---------------------------------------------------orz

TvTvTvTvTvT

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int mod=26;
string s[1005];
double x[30];
double oc[30],sum1;
//oc记录字符串中字母出现次数 
int tot;
struct rex{
    double p;
}p[26];
struct rec{
    string s;
    int len;
    int bo[10000];//小写0 大写1 符号2 
}qaq[1005];
double sq()
{
    double w=0;
    for(int i=0;i<26;i++)
        w+=(p[i].p-x[i])*(p[i].p-x[i]);
    return w;
}
int main()
{
    //freopen("decode.in","r",stdin);
    //freopen("decode.out","w",stdout);
    for(int i=0;i<26;i++){
        scanf("%lf\n",&p[i].p);
     //(-w-|||) 不 //(-u-|||) 写 //(-A-|||) 换 //(-a-|||) 行 //(-o-|||) 好 //(-^-|||) 凉 //(-v-|||) 爽 } while(getline(cin,s[++tot])){ qaq[tot].s=s[tot]; int len=qaq[tot].len=s[tot].length(); for(int i=0;i<len;i++){ if(s[tot][i]>='a' && s[tot][i]<='z'){ oc[s[tot][i]-'a']++; qaq[tot].bo[i]=0; } else if(s[tot][i]>='A'&&s[tot][i]<='Z'){ oc[s[tot][i]-'A']++; qaq[tot].bo[i]=1; } else qaq[tot].bo[i]=2; } } for(int i=0;i<26;i++) sum1+=oc[i]; int ak=0; double sq1=999999999999; for(int k=0;k<26;k++){ for(int i=0;i<26;i++) x[i]=oc[(i+k)%26]/sum1; if(sq1>sq()){ sq1=sq(); ak=k; } } for(int i=1;i<tot;i++){ int len=qaq[i].len; for(int j=0;j<len;j++){ char ch=qaq[i].s[j]; if(qaq[i].bo[j]==2) cout<<ch; else if(qaq[i].bo[j]==0){ cout<<(char)((ch-'a'-ak+52)%26+'a'); } else if(qaq[i].bo[j]==1){ cout<<(char)((ch-'A'-ak+52)%26+'A'); } } cout<<endl; } return 0; }

 T3休息

 

【问题描述】

    休息的时候,可以放松放松浑身的肌肉,打扫打扫卫生,感觉很舒服。在某一天,某LMZ开始整理他那书架。已知他的书有n本,从左到右按顺序排列。他想把书从矮到高排好序,而每一本书都有一个独一无二的高度Hi。他排序的方法是:每一次将所有的书划分为尽量少的连续部分,使得每一部分的书的高度都是单调下降,然后将其中所有不少于2本书的区间全部翻转。重复执行以上操作,最后使得书的高度全部单调上升。可是毕竟是休息时间,LMZ不想花太多时间在给书排序这种事上面。因此他划分并翻转完第一次书之后,他想计算,他一共执行了多少次翻转操作才能把所有的书排好序。LMZ惊奇地发现,第一次排序之前,他第一次划分出来的所有区间的长度都是偶数。

 

【输入格式】rest.in

    第一行一个正整数n, 为书的总数。

    接下来n行,每行仅一个正整数Hi,为第i本书的高度。

【输出格式】rest.out

    仅一个整数,为LMZ需要做的翻转操作的次数。

样例输入

样例输出

6

5 3 2 1 6 4

3

【样例解释】

    第一次划分之后,翻转(5,3,2,1),(6,4)。之后,书的高度为1 2 3 5 4 6,然后便是翻转(5,4)即可。

数据范围与约定

    对于10%的数据:n<=50

    对于40%的数据:n<=3000

    对于100%的数据:1<=n<=100000, 1<=Hi<=n

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int h[1000010],r[1000010],n,now;
long long ans=0;
inline int read()
{
    int f=0;
    char ch=getchar();
    while(ch>'9' || ch<'0')
        ch=getchar();
    while(ch>='0' && ch<='9'){
        f=f*10+ch-'0';
        ch=getchar();
    }
    return f;
}
void msort(int ll,int rr)
{
    if(ll==rr)
        return ;
    int mid=(ll+rr)>>1;
    msort(ll,mid);
    msort(mid+1,rr);//递归 
    int i=ll,j=mid+1,k=ll;
    while(i<=mid && j<=rr)
    {
        if(h[i]<=h[j])
            r[k++]=h[i++];//先赋值再+1
        else {
            r[k++]=h[j++];
            ans+=(long long)mid-i+1;//重点    
        }
    }
    while(i<=mid){
        r[k++]=h[i++];
    }
    
    while(j<=rr) {
        r[k++]=h[j++];
    }
    for(int i=ll;i<=rr;i++)
        h[i]=r[i]; 
}
int main()
{
    n=read();h[n+1]=0x3f3f3f3f;
    for(int i=1;i<=n;i++)
        h[i]=read();
    //区间翻转 
    for(int i=1;i<=n;i++)
    {
        if(h[i]<h[i+1])
        {
            sort(h+now+1,h+i+1);
            now=i;
            ans++;
        }
    }
    
    //归并排序求逆序对
    msort(1,n);
    printf("%lld",ans);
    return 0;
}

 

posted @ 2019-07-24 20:49  Markill  阅读(264)  评论(2编辑  收藏  举报