Bestcoder round#34 解题报告
2016-05-23 23:31
232 查看
1001 Go to movies
枚举暴力一发就行。#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<stack> #include<queue> #include<vector> #include<bitset> using namespace std; int n,m; int main() { while (cin>>n>>m) { int ans=1100000; for (int i=1;i<=m;i++) { int a,b; cin>>a>>b; int d=n/a; if (n%a) d++; ans=min(ans,d*b); } cout<<ans<<endl; } return 0; }
1002 Building Blocks
首先我们很容易知道,题目无解当且仅当∑h[i]<W∗H 。对于一段长为W的序列,高度小于H部分的高度和为∑h[i](h[i]<H),高度大于H部分的高度和为∑h[i](h[i]>H),而最小的移动数应为max(∑h[i](h[i]<H),∑h[i](h[i]>H)) 。然后我们线性扫一遍就行了。#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<stack> #include<queue> #include<vector> #include<bitset> using namespace std; typedef long long LL; LL n,w,h; LL sum,a[151000]; LL ans; LL l,r; LL cal() { LL res=l+r-min(l,r); return res; } int main() { while (scanf("%I64d %I64d %I64d",&n,&w,&h)==3) { sum=0; memset(a,0,sizeof(a)); for (int i=1;i<=n;i++) scanf("%I64d",&a[i+w]),sum+=a[i+w]; if (sum<w*h) { printf("-1\n"); continue; } l=0,r=0; for (int i=1;i<=w;i++) { if (a[i]<h) l+=h-a[i]; else r+=a[i]-h; } ans=cal(); for (int i=1;i<=w+n;i++) { if (a[i]<h) l-=h-a[i]; else r-=a[i]-h; if (a[i+w]<h) l+=h-a[i+w]; else r+=a[i+w]-h; ans=min(ans,cal()); } printf("%I64d\n",ans); } return 0; }
1003 Building Blocks II
判断无解的方法与上题相同。考虑一段序列,不难发现,使它移动次数最少的高度应为整个序列的平均高度(同时还得比H高)。由于平均高度不一定为整数,所以我们还得考虑取整后+1这一高度。上题由于高度确定,所以可以O(1)维护两部分和的值,而此题不确定,所以我们需要利用树状数组来维护这一部分的和。#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<stack> #include<queue> #include<vector> #include<bitset> using namespace std; typedef long long LL; const int maxn=60000; LL nu[maxn+10]; LL height[maxn+10]; const LL INF=1e18; inline int lowbit(int x) { return (x&-x); } void add(LL *fenwick,int x,LL value) { for (int i=x;i<=maxn;i+=lowbit(i)) fenwick[i]+=value; } LL get(LL *fenwick,int x) { LL sum=0; for (int i=x;i;i-=lowbit(i)) sum+=fenwick[i]; return sum; } LL nowh; int n; LL h,w; LL v[3*maxn+10]; LL ansx,ans,sum; void check(LL x) { if (x<h||x*w>sum) return; LL minn=x*get(nu,x-1)-get(height,x-1),maxx=get(height,55001)-get(height,x)-x*(get(nu,55001)-get(nu,x)); LL res=max(minn,maxx); if (res<ans||((res==ans)&&(x>ansx))) { ans=res; ansx=x; } } int main() { while (scanf("%d %I64d %I64d",&n,&w,&h)==3) { memset(nu,0,sizeof(nu)); memset(height,0,sizeof(height)); for (int i=0;i<3*maxn+10;i++) v[i]=1; sum=0; h++; for (int i=1;i<=n;i++) scanf("%I64d",&v[i+maxn]),++v[i+maxn],sum+=v[i+maxn]; if (sum<w*h) { printf("-1\n"); continue; } nowh=w; add(nu,1,w); add(height,1,w); ans=INF; ansx=0; for (int i=maxn+1;i<=n+maxn+w;i++) { nowh-=v[i-w]; add(nu,v[i-w],-1); add(height,v[i-w],-v[i-w]); nowh+=v[i]; add(nu,v[i],1); add(height,v[i],v[i]); LL x=nowh/w; check(x); check(x+1); check(h); } if (ans==INF) printf("-1\n"); else printf("%I64d %I64d\n",ansx-1,ans); } return 0; }
1004 Go to movies II
静态的逆序对我们可以用树状数组维护,由于此题中有插入和删除操作,会改变相对位置,所以需要利用数据结构套数据结构的方式。由于此题可以O(nn−−√)搞,所以我们就用块状链表套树状数组实现。#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<stack> #include<queue> #include<vector> #include<bitset> using namespace std; const int maxn=21000; inline int lowbit(int x) { return (x&-x); } void add(int *fenwick,int x,int value) { for (int i=x;i<=maxn;i+=lowbit(i)) fenwick[i]+=value; } int get(int *fenwick,int x) { int sum=0; for (int i=x;i;i-=lowbit(i)) sum+=fenwick[i]; return sum; } const int m=350; struct data { int s,a[2*m+5]; int c[21000]; data *next; data() { memset(c,0,sizeof(c)); next=NULL; } }; data *root; void insert(int x,int pos) { if (root==NULL) { root=new(data); root->s=1; root->a[1]=x; add(root->c,x,1); return ; } data *k=root; while (pos>k->s && k->next!=NULL) { pos-=k->s; k=k->next; } memmove(k->a+pos+1,k->a+pos,sizeof(int)*(k->s-pos+1)); k->s++; k->a[pos]=x; add(k->c,x,1); if (k->s==2*m) { data *t=new(data); t->next=k->next; k->next=t; memcpy(t->a+1,k->a+m+1,sizeof(int)*m); for (int i=1;i<=m;i++) { add(k->c,t->a[i],-1); add(t->c,t->a[i],1); } t->s=k->s=m; } } void del(int pos) { data *k=root; while (pos>k->s && k->next!=NULL) { pos-=k->s; k=k->next; } add(k->c,k->a[pos],-1); memmove(k->a+pos,k->a+pos+1,sizeof(int)*(k->s-pos)); k->s--; } int find(int pos) { data *k=root; while (pos>k->s && k->next!=NULL) { pos-=k->s; k=k->next; } return (k->a[pos]); } void destroy(data *k) { if (k->next!=NULL) destroy(k->next); delete(k); } int cal(int pos) { int res=0; data *k=root; int x=find(pos); while (pos>k->s && k->next!=NULL) { pos-=k->s; res+=get(k->c,20000)-get(k->c,x); k=k->next; } for (int i=1;i<pos;i++) if (k->a[i]>x) res++; for (int i=pos+1;i<=k->s;i++) if (k->a[i]<x) res++; while (k->next!=NULL) { k=k->next; res+=get(k->c,x-1)-get(k->c,0); } return res; } int ans; int n,q; int main() { while (scanf("%d %d",&n,&q)==2) { root=NULL; ans=0; for (int i=1;i<=n;i++) { int x; scanf("%d",&x); insert(x,i); ans+=cal(i); } for (int i=1;i<=q;i++) { int op; scanf("%d",&op); if (op==0) { int x,y; scanf("%d %d",&x,&y); x++; insert(y,x); ans+=cal(x); } else { int x; scanf("%d",&x); ans-=cal(x); del(x); } printf("%d\n",ans); } destroy(root); } return 0; }
相关文章推荐
- ROS探索(2)——仿真器的搭建
- request和response对象
- android插入SQLite中文乱码问题
- 4-Bom&Dom总结篇
- windows,linux,mac生成ssh public key 和 private key
- Android Architecture(Is Activity God?)
- 2016春季练习——矩阵快速幂
- Eclipse_配置文件导出
- 一只Linux小白,啊哈哈。。。以后就将自己的学习心得与大家分享啦!希望大家可以指出我的错误与不足之处
- 大学毕业4年-回顾和总结(9)-股权投资1年,给自己一个答卷(好狗狗、皇包车、职业梦、比呀比、易途8)(创业有风险,投资需谨慎)
- 大学毕业4年-回顾和总结(9)-股权投资1年,给自己一个答卷(好狗狗、皇包车、职业梦、比呀比、易途8)(创业有风险,投资需谨慎)
- c++作业-6
- 大学毕业4年-回顾和总结(9)-股权投资1年,给自己一个答卷(好狗狗、皇包车、职业梦、比呀比、易途8)(创业有风险,投资需谨慎)
- (LeetCode) 3、Longest Substring Without Repeating Characters
- 总结
- 滚动轴承故障特征频率的计算
- Recylerview局部刷新
- java-微信新版自动聊天助手
- Linux下的文件查找命令——find
- jQuery height()、innerHeight()、outerHeight()函数的区别详解