百度之星2015初赛#1
超级赛亚ACMer
题解
玛雅!Orz 看错题目了、、一开始、我就说怎么觉得看似贪心但是仔细一想有不对、
把所有人拍个序,我们每次贪心的取能取到的最大的能激发潜力的人。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
//WNJXYK //while(true) RP++; #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; int n,m,k,T,flag; long long num[10010]; int main(){ scanf("%d",&T); for (int Rt=1;Rt<=T;Rt++){ cout<<"Case #"<<Rt<<':'<<endl; scanf("%d%d%d",&n,&m,&k);flag=0; for(int i=1;i<=n;i++) scanf("%I64d",&num[i]); sort(num+1,num+n+1); long long s=0,c,i; for(i=1;i<=n;i++) if(num[i]>m) break; if(i==1){ cout<<"madan!"<<endl; continue; } s=i-1,c=num[s]; for(int i=k;i>=0;i--){ int j=s; if(num[j+1]-num[j]>k) break; if(num[n]<=c+i){ cout<<"why am I so diao?"<<endl; flag=1; break; } while(num[j]<=c+i) j++; j--; s=j;c=num[j]; } if(!flag) cout<<"madan!"<<endl; } return 0; } |
找连续数
题解
这到题目每个询问暴力枚举区间,前缀和维护区间和,ST表维护区间最小值,然后暴力处理某一区间是否有重复的数,这样每个询问加起来是O(n)的。于是O(NM)就行了!「如果吧ST表当作O(1)。。。」然后区间内无重复的数,且区间和和用最小值计算出来的一样那么就是一个合法的答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
//WNJXYK //while(true) RP++; #include<iostream> #include<cstdio> #include<algorithm> #include<map> #include<cstring> using namespace std; const int Maxn=10010; int m,n,k,Ans; int flag; long long num[Maxn]; long long minNum,sumNum; map<long long,int> Hash; long long tHash[Maxn*2]; int tot; long long sum[Maxn]; int vis[Maxn*2]; long long stTableMin[Maxn][35],preLog2[Maxn]; void StPrepare(){ preLog2[1]=0; for(int i=2;i<=n;i++){ preLog2[i]=preLog2[i-1]; if((1<<preLog2[i]+1)==i) preLog2[i]++; } for(int i=n;i>=0;--i){ stTableMin[i][0]=num[i]; for(int j=1;(i+(1<<j)-1)<=n;++j) stTableMin[i][j]=min(stTableMin[i][j-1],stTableMin[i+(1<<j-1)][j-1]); } } int queryMin(int l,int r){ int len=r-l+1,k=preLog2[len]; return min(stTableMin[l][k],stTableMin[r-(1<<k)+1][k]); } int main(){ printf("Case #1:\n"); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%I64d",&num[i]); for (int i=1;i<=n;i++) {tHash[i*2-1]=num[i];tHash[i*2]=num[i]+1;} sort(tHash+1,tHash+n*2+1); tHash[0]=-1; for (int i=1;i<=n*2;i++){ if (tHash[i]!=tHash[i-1])Hash[tHash[i]]=++tot; } for (int i=1;i<=n;i++) num[i]=Hash[num[i]]; sum[0]=0; for (int i=1;i<=n;i++) sum[i]+=sum[i-1]+num[i]; StPrepare(); for (int i=1;i<=m;i++){ scanf("%d",&k); Ans=0;flag=0; memset(vis,0,sizeof(vis)); for (int j=1;j<=k;j++){ vis[num[j]]++; if (vis[num[j]]==2) flag++; } if (!flag){ minNum=queryMin(1,k); sumNum=sum[k]-sum[0]; if (sumNum==(long long)(minNum+minNum+k-1)*(long long)k/(long long)2) Ans++; //printf("True\n"); } for (int left=2;left<=n;left++){ int right=left+k-1; if (right>n) break; vis[num[left-1]]--; if (vis[num[left-1]]==1) flag--; vis[num[right]]++; if (vis[num[right]]==2) flag++; if (!flag){ minNum=queryMin(left,right); sumNum=sum[right]-sum[left-1]; if (sumNum==(long long)(minNum+minNum+k-1)*(long long)k/(long long)2) Ans++; } } printf("%d\n",Ans); } return 0; } |
序列变换
题解
二分答案,然后我们贪心验证就好、、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
//WNJXYK //while(true) RP++; #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; const int Maxn=100000+10; int num[Maxn],n,T,tmp[Maxn]; inline bool check(int l){ for(int i=1;i<=n;i++) tmp[i]=num[i]; tmp[1]=num[1]-l; for(int i=2;i<=n;i++) if(num[i]+l<=tmp[i-1]) return false; else tmp[i]=max(num[i]-l,tmp[i-1]+1); return true; } int main(){ scanf("%d",&T); for (int Rt=1;Rt<=T;Rt++){ scanf("%d",&n); cout<<"Case #"<<Rt<<':'<<endl; for(int i=1;i<=n;i++) scanf("%d",&num[i]); int l=0,r=1000000,ans=0; while(l<=r){ int mid=(l+r)>>1; if(check(mid)){ ans=mid; r=mid-1; }else{ l=mid+1; } } cout<<ans<<endl; } return 0; } |
KPI
题解
评测机一定是开O2了、、、直接Vector就水过去了、、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
//WNJXYK //while(true) RP++; #include<iostream> #include<cstdio> #include<algorithm> #include<map> #include<set> #include<queue> #include<string> #include<cstring> #include<vector> using namespace std; vector<int> V; int n; char ord[10]; int num; int stack[10010]; int l,r; int siz; inline void solve(){ V.clear(); V.reserve(n+10); r=0; l=1; siz=0; for (int i=1;i<=n;i++){ scanf("%s",ord); if (ord[0]=='i') scanf("%d",&stack[++r]); if (ord[0]=='i'){ siz++; //printf("Insert %d\n",stack[r]); V.insert(upper_bound(V.begin(),V.end(),stack[r]),stack[r]); }else if (ord[0]=='o'){ //printf("Out %d\n",stack[l]); V.erase(lower_bound(V.begin(),V.end(),stack[l])); l++; siz--; }else{ //printf("Siz:%d\n",siz); printf("%d\n",V[siz/2]); } } } int T; int main(){ while(scanf("%d",&n)!=EOF){ T++; printf("Case #%d:\n",T); solve(); } return 0; } |
矩形面积
题解
旋转卡壳+凸包!(其实我并不会做 见BZOJ1185
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
//WNJXYK //while(true) RP++; #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #define MAXN 51000 #define EPS 1e-10 using namespace std; int n; double minsqr; int dcmp(double x){ if(fabs(x)<EPS) return 0; if(x>-EPS) return 1; return -1; } struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} void read(){ scanf("%lf%lf",&x,&y); //cout<<x<<" "<<y<<endl; } }points[MAXN],stack[MAXN<<1],ans[10]; //ans保存最小覆盖矩形的四个顶点 Point operator-(Point a,Point b){ return Point(a.x-b.x,a.y-b.y); } Point operator*(Point a,double b){ return Point(a.x*b,a.y*b); } Point operator+(Point a,Point b){ return Point(a.x+b.x,a.y+b.y); } double cross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } double dot(Point a,Point b,Point c){ return (b.x-a.x)*(c.x-b.x)+(b.y-a.y)*(c.y-b.y); } double dist(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int top=0; bool cmp(Point a,Point b){ if(!dcmp(a.x-b.x)) return a.y<b.y; return a.x<b.x; } bool operator<(Point a,Point b){ if(!dcmp(a.y-b.y)) return a.x<b.x; return a.y<b.y; } void Graham(){ sort(points+1,points+n+1,cmp); for(int i=1;i<=n;i++) { while(top>=2&&dcmp(cross(stack[top-1],stack[top],points[i])<=0)) top--; stack[++top]=points[i]; } int tmp=top; for(int i=n-1;i>=1;i--) { while(top>=tmp+1&&dcmp(cross(stack[top-1],stack[top],points[i])<=0)) top--; stack[++top]=points[i]; } top--; } void rotcalip(){ int left=1,right=1,up=1; for(int i=1;i<=top;i++){ while(dcmp(cross(stack[up+1],stack[i],stack[i+1])-cross(stack[up],stack[i],stack[i+1]))>=0) up=up%top+1; while(dcmp(dot(stack[right+1],stack[i+1],stack[i])-dot(stack[right],stack[i+1],stack[i]))>=0) right=right%top+1; if(i==1) left=right; while(dcmp(dot(stack[left+1],stack[i],stack[i+1])-dot(stack[left],stack[i],stack[i+1]))>=0) left=left%top+1; double L=dist(stack[i],stack[i+1]); double H=cross(stack[i+1],stack[up],stack[i])/L; double bottom=(fabs(dot(stack[i],stack[i+1],stack[left])/L)+fabs(dot(stack[i],stack[i+1],stack[right])/L)); double nowsqr=bottom*H; if(nowsqr<minsqr) { minsqr=nowsqr; ans[0]=stack[i]+(stack[i+1]-stack[i])*((fabs(dot(stack[i],stack[i+1],stack[right]))/L+L)/L); ans[1]=ans[0]+(stack[right]-ans[0])*(H/dist(stack[right],ans[0])); ans[2]=ans[1]+(stack[up]-ans[1])*(bottom/dist(stack[up],ans[1])); ans[3]=ans[2]+(stack[left]-ans[2])*(H/dist(stack[left],ans[2])); } } } int solve(){ minsqr=1e12; scanf("%d",&n); n*=4;top=0; for(int i=1;i<=n;i++) points[i].read(); Graham(); rotcalip(); int Ans=(int)(minsqr+0.5); printf("%d\n",Ans); return 0; } int T; int main(){ scanf("%d",&T); for (int i=1;i<=T;i++){ printf("Case #%d:\n",i); solve(); } } |

原文链接:百度之星2015初赛#1
WNJXYKの博客 版权所有,转载请注明出处。
还没有任何评论,你来说两句吧!