APIO2015泛做
可以在UOJ上提交也可以在bzoj上提交(权限)
A. Bali Sculptures
对于前72%的数据,按位考虑,然后跑一点沙茶dp就行了。
dp:用f[x][y]表示前x位分为y段是否满足条件。
对于最后29%的数据,我们改一下dp方程。
dp:用f[x]表示前x位满足条件至少要分几段。
结论:傻逼题
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <vector> #include <math.h> #include <limits> #include <set> #include <map> using namespace std; #define SZ 2066 typedef long long ll; int n,a,b,yy[SZ]; #define S 50 ll inn=0,sum[SZ]; bool dp2[SZ][SZ]; bool chk2() { for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dp2[i][j]=0; dp2[0][0]=1; for(int i=0;i<n;i++) //分i段 { for(int j=0;j<n;j++) { if(!dp2[i][j]) continue; for(int k=j+1;k<=n;k++) { if(((sum[k]-sum[j])|inn)==inn) dp2[i+1][k]=1; } } } for(int i=a;i<=b;i++) if(dp2[i][n]) return 1; return 0; } int dp1[SZ]; const int inf=1000000000; bool chk1() { dp1[0]=0; for(int i=1;i<=n;i++) dp1[i]=inf; for(int j=0;j<n;j++) { if(dp1[j]==inf) continue; for(int k=j+1;k<=n;k++) { if(((sum[k]-sum[j])|inn)==inn) dp1[k]=min(dp1[k],dp1[j]+1); } } return dp1[n]<=b; } int main() { scanf("%d%d%d",&n,&a,&b); for(int i=1;i<=n;i++) scanf("%d",yy+i), sum[i]=sum[i-1]+yy[i]; inn=(1LL<<S)-1; for(int i=S;i>=1;i--) { inn^=1LL<<(i-1); if(!((a==1)?chk1():chk2())) inn^=1LL<<(i-1); } printf("%lld\n",inn); }
B. Jakarta Skyscrapers
据说可以卡时过?然而UOJ有hack啊根本过不了
等知道正解了再来补
C. Palembang Bridges
一座桥的时候,容易发现要建在中位数的地方。
两座桥的时候,按照每个人的家和办公室位置和排序后,一定存在一个分割点使得前缀都走左边的桥,后缀都走右边的桥,这似乎挺显然的。
然后离散完随手树状数组+二分维护一下中位数啥的即可。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <vector> #include <math.h> #include <limits> #include <set> #include <map> using namespace std; #define SZ 666666 typedef long long ll; int K,n,as[SZ],bs[SZ],ap[SZ]; ll ans=0; int Abs(int x) {return (x>=0)?x:-x;} ll a_1() { ll aa=0; int nn=0; for(int i=1;i<=n;i++) ap[++nn]=as[i]; for(int i=1;i<=n;i++) ap[++nn]=bs[i]; sort(ap+1,ap+1+nn); int md=ap[(nn+1)>>1]; for(int i=1;i<=nn;i++) aa+=Abs(ap[i]-md); return aa; } typedef pair<int,int> pii; pii zs[SZ]; bool cmp(pii a,pii b) {return a.first+a.second<b.first+b.second;} #define SN 233333 struct Bits { ll bits[SZ]; ll sum(int x) { ll ans=0; for(;x>=1;x-=x&-x) ans+=bits[x]; return ans; } ll sum(int l,int r) {return sum(r)-sum(l-1);} void edit(int x,ll y) { for(;x<=SN;x+=x&-x) bits[x]+=y; } void clr() {for(int i=1;i<=SN;i++) bits[i]=0;} }B1,B2; ll zd[SZ],fd[SZ]; #define ls(x) (lower_bound(ap+1,ap+1+nn,x)-ap) ll a_2() { ll aa=20000000000000000LL; int nn=0; for(int i=1;i<=n;i++) ap[++nn]=as[i]; for(int i=1;i<=n;i++) ap[++nn]=bs[i]; sort(ap+1,ap+1+nn); nn=unique(ap+1,ap+1+nn)-ap-1; for(int i=1;i<=n;i++) zs[i].first=as[i], zs[i].second=bs[i]; sort(zs+1,zs+1+n,cmp); B1.clr(); B2.clr(); for(int i=1;i<=n;i++) { int A=ls(zs[i].first),B=ls(zs[i].second); B1.edit(A,1); B2.edit(A,zs[i].first); B1.edit(B,1); B2.edit(B,zs[i].second); int l=0,r=nn; while(l<r) { int mid=(l+r)>>1; int s=B1.sum(mid); if(s<i) l=mid+1; else r=mid; } int mn=ap[l]; ll cans=B1.sum(l)*mn-B2.sum(l)+B2.sum(l,nn)-B1.sum(l,nn)*mn; zd[i]=cans; } B1.clr(); B2.clr(); for(int i=n;i>=1;i--) { int A=ls(zs[i].first),B=ls(zs[i].second); B1.edit(A,1); B2.edit(A,zs[i].first); B1.edit(B,1); B2.edit(B,zs[i].second); int l=0,r=nn; while(l<r) { int mid=l+r>>1; int s=B1.sum(mid); if(s<n+1-i) l=mid+1; else r=mid; } int mn=ap[l]; ll cans=B1.sum(l)*mn-B2.sum(l)+B2.sum(l,nn)-B1.sum(l,nn)*mn; fd[i]=cans; } for(int i=1;i<=n+1;i++) aa=min(aa,zd[i-1]+fd[i]); return aa; } int main() { int N; scanf("%d%d",&K,&N); for(int i=1;i<=N;i++) { char a[3],c[3]; int b,d; scanf("%s%d%s%d",a,&b,c,&d); if(a[0]==c[0]) { ans+=Abs(b-d); continue; } ++n; as[n]=b; bs[n]=d; } if(K==1) printf("%lld\n",a_1()+ans+n); else printf("%lld\n",a_2()+ans+n); }