弱鸡儿长乐爆零旅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  阅读(294)  评论(2)    收藏  举报