弱鸡儿长乐爆零旅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; }