[Offer收割]编程练习赛7
图片排版
题目链接:
http://hihocoder.com/problemset/problem/1365解题思路:
比较容易想到是O(n^2)的解决方案,遍历n种删除可能,每次遍历O(n)时间求总高度。前者优化比较困难,因而想办法优化每次遍历求高度的时间。
由前往后遍历,当删除第i个图片时,先前的图片排版是连续的,从而通过计数器等累加方法可以求得已完整行的总高度preSum,以及当前未完整行的w,h。
AC代码:
#include<bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; const int N = 100005; int n,m; int wi[N],hi[N],t[N]; void attach(int i,int &w,int &h){ if (w+wi[i] > m) h = max(h,(int)ceil(1.0*(m-w)*hi[i]/wi[i])); else h = max(h, hi[i]); w = min(m, w+wi[i]); } int calc(int i,int w,int h){ while(i < n && w < m) attach(i++,w,h); return h+t[i]; } void solve(){ int ans = INF,w,h,preSum; w = h = preSum = 0; for(int i = 0; i < n; ++i){ int tmp = calc(i+1,w,h); ans = min(ans, preSum+tmp); attach(i,w,h); if(w == m){ preSum += h; w = h = 0; } } printf("%d\n",ans); } int main(){ while(~scanf("%d%d",&m,&n)){ for(int i = 0; i < n; ++i) scanf("%d%d",&wi[i],&hi[i]); for(int i = n-1; i >= 0; --i) t[i] = calc(i,0,0); solve(); } return 0; }
逆序单词
题目链接:
http://hihocoder.com/problemset/problem/1366
解题思路:
利用map的性质即可轻易求解。AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; map<string,int> ma; map<string,int>::iterator it; int main(){ int n; while(~scanf("%d",&n)){ ma.clear(); string str; for(int i = 0; i < n; ++i){ cin>>str; int len = str.size(); if(!ma[str]){ reverse(str.begin(),str.end()); } //cout<<str<<endl; ++ma[str]; } ll ans = 0; for(it = ma.begin(); it != ma.end(); ++it){ ans += (ll)(it->second)*(it->second-1)/2; } printf("%lld\n",ans); } return 0; }