说些感触。
= =、哎,说起来重现还真是好气啊。
出去的大二过去两题打铁,今天我们队边玩边打过了4题,有点不甘心啊。= =、对教练略无奈。
-------------------------
比赛经验:
今天一开始,我洗完澡回来,比赛已经开始15分钟了,yhp和zmy都还在看题意,然后zmy在我来的时候已经在敲02了(其实是03,他说是02),然后我就和yhp讨论01,01yhp说完题意,一脸蒙比,因为知道01是水题吧,所以就开始瞎yy........(中间yy略去),后来我们过了01(wa了很多,我记得第一发T了,数组开小,这种低智商的错误也犯了)。然后窝去找zmy看03,C题一读完,卧槽,那么简单。。。zmy陷入了一个很烂的思路(其实这个每个人都有),但是严重的是,如果是现场赛,那不就完蛋了。我一直在想一个最不好的情况,那就是两个人在搞一道题目,而另一个人陷入了一道不是很难的水题不能自拔。这是最烂的,首先zmy因为这题(后来yhp和窝开始重新搞,wa了一发,也过了)心态不好了,心态很重要很重要!!比赛的时候心态很重要,不要脸地说,今天4题有3题基本上是我主导思路,然后过的,自信很重要,心态很重要!后来搞那个06,yhp瞎yy了一个方案,后来zmy搞出来在<8的情况是错的,后来一致决定<8暴力,然后wa了,因为输出用了%d....2333,最后的02,一直想一直想,最后队友给我讲了有可能环带有支路,那么就是强连通缩点,搞完1A。
应该在现场赛就能拿铜了。。。。。心好痛。。。。。。
不过真的,今天边玩边打场,比赛经验就是:心态很重要!
还有以后的策略,除非是很水很水的题,操盘>=两个人!而另一个人要死命去读别的题,做好一旦那个题A出或者没A出的衔接工作,每个人都要有担当;
写几发题解;
---------------
11还在酝酿。。。。。。
01:
题意:
给你n个值,让你搞成m个相等的值,一种操作是把a[i]只能分成相邻两部分,另一种操作是把a[i]和a[i+1]合并,求最小操作数;
思路:
首先肯定是求个所有值的sum,并且sum%m==0,搞一个平均值aver
就是如果对于当前a[i]<aver,那么就往前面拿,如果是a[i]+a[i+1]<=aver那么就是直接合并,最后出来的时候判断一下a[i]就好了;
如果对于a[i]>aver,那么就要分,那么肯定是分aver出去,分到小于等于aver为止,然后还要处理剩下的;
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #include <queue> #include <stack> using namespace std; #define INF 0x3f3f3f #define pi acos(-1.0) #define mod 9973 typedef long long LL; const int MAX=100010; LL n,m; LL a[MAX]; int main() { LL t,i,j; scanf("%d",&t); int cas=1; while(t--) { LL sum=0; scanf("%d%d",&n,&m); for(i=0;i<n;i++) { scanf("%lld",&a[i]); sum+=a[i]; } printf("Case #%d: ",cas++); if(sum%m!=0) { printf("-1 "); continue; } LL aver=sum/m; LL cont=0; for(i=0;i<n;i++) { if(a[i]<aver) { LL tmp=a[i]; while(i+1<n&&(tmp+a[i+1])<=aver) { tmp+=a[i+1]; i++; cont++; } if(tmp<aver) { cont+=2; a[i+1]-=aver-tmp; } } else if(a[i]>aver) { while(a[i]>aver) { cont++; a[i]-=aver; } if(i+1<n&&a[i]<aver) { LL tmp=a[i]; while(i+1<n&&(tmp+a[i+1])<=aver) { tmp+=a[i+1]; i++; cont++; } if(tmp<aver) { cont+=2; a[i+1]-=aver-tmp; } } } } printf("%lld ",cont); } return 0; }
02:
题意:
给你n个炸弹(一开始理解成了灯。。)的坐标,范围,花费,a炸了,b在a炸弹的边界或者里面,b也炸了,以此类推;
思路:
强连通,缩点,然后取一个点集里面最小的花费作为这个点的花费,然后把入度为零的点的花费加起来就好了;
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> #include <stack> using namespace std; const double INF = 0x3f3f3f3f; typedef long long LL; const int N = 1e3+10; struct asd{ LL x; LL y; LL w; LL cash; }; asd q[N]; int pre[N]; int ma[N][N]; int dfn[N]; int low[N]; int stap[N]; int vis[N]; int in[N]; int tp,p,cnt; LL ww[N]; int kr[N]; int n; bool Judge(int i,int j) { if(i==j) return false; if(((q[i].x-q[j].x)*(q[i].x-q[j].x)+(q[i].y-q[j].y)*(q[i].y-q[j].y))<=(q[i].w*q[i].w)) return true; return false; } void tarjan(int u) { dfn[u]=low[u]=++tp; stap[++p]=u; vis[u]=1; for(int i=1;i<=n;i++) { if(!ma[u][i]) continue; if(!dfn[i]) { tarjan(i); low[u]=min(low[u],low[i]); } else if(vis[i]) { low[u]=min(low[u],dfn[i]); } } if(dfn[u]==low[u]) { cnt++; int temp; while(1) { temp=stap[p]; vis[temp]=0; in[temp]=cnt; ww[cnt]=min(ww[cnt],q[temp].cash); p--; if(temp==u) { break; } } } } void fun() { memset(kr,0,sizeof(kr)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(ma[i][j]&&in[i]!=in[j]) { kr[in[j]]++; } } } LL ans=0; for(int i=1;i<=cnt;i++) { if(!kr[i]) { ans+=ww[i]; } } printf("%lld ",ans); } void init() { memset(ma,0,sizeof(ma)); memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(ww,INF,sizeof(ww)); } int main() { int T,cas=1; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld%lld%lld%lld",&q[i].x,&q[i].y,&q[i].w,&q[i].cash); init(); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(Judge(i,j)) ma[i][j]=1; } } tp=p=cnt=0; for(int i=1;i<=n;i++) { if(!dfn[i]) { tarjan(i); } } printf("Case #%d: ",cas++); fun(); } return 0; }
03:
题意:
有一辆车,通过n个位置,通过每个位置的时间点都是整数,在整个过程中车的速度是非递减的。
思路:
那么就是说最后那个区间速度最大,时间最短,而且是整数秒,那么就是1秒,然后对于每个区间就是求一个向上取整时间(以前和队友考虑过)(n+m-eps)/m;
(被除数+除数-精度)/除数;)也没怎么注意就用了long long
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #include <queue> #include <stack> using namespace std; #define INF 0x3f3f3f #define pi acos(-1.0) #define mod 9973 typedef long long LL; const double eps=1e-6; const int MAX=100010; int n,m; double a[MAX],b[MAX]; int main() { int i,j; int t; scanf("%d",&t); int cas=1; while(t--) { scanf("%d",&n); for(i=1;i<=n;i++) { if(i==1) { scanf("%lf",&a[i]); b[i]=a[i]; } else { scanf("%lf",&a[i]); b[i]=a[i]-a[i-1]; } } double tmp=b[n]; LL ans=0; ans+=1; for(i=n-1;i>=1;i--) { if(b[i]<=tmp) { ans+=1; tmp=b[i]; } else { LL tt=(b[i]+tmp-eps)/tmp; ans+=tt; tmp=b[i]/(double)tt; // printf("%lld ",tt); } // printf("%lf ",tmp); } printf("Case #%d: ",cas++); printf("%lld ",ans); } return 0; }
06:
题意:
给你一串数,让你依次分割成5串,做+-*/运算,*/优先,求最大值;
思路:
队友一开始想就是前面位数越多越好,就是两种可能首位+第二位到倒数第四位或者首位到倒数第五位构成的数+倒数第四位;
后来长度为6或7的时候有出路,一致同意<=8的情况下暴力,然后用暴力测所有情况,感觉没问题就过了;
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #include <queue> #include <stack> using namespace std; #define INF 0x3f3f3f #define pi acos(-1.0) #define mod 9973 typedef long long LL; const double eps=1e-6; const int MAX=100010; int n,m; char s[21]; LL get_num(int ss,int t) { LL ans=0; for(int i=ss; i<t; i++) { ans=ans*10+s[i]-'0'; } return ans; } int main() { int i,j,k,h; int t; scanf("%d",&t); int cas=1; while(t--) { scanf("%s",s); printf("Case #%d: ",cas++); n=strlen(s); LL ans1=0; ans1=(s[n-3]-'0')*(s[n-2]-'0')/(s[n-1]-'0'); ans1=-ans1; LL sum1=0,sum2=0; if(n<=8) { LL ans=-INF; for(i=1; i<(n-3); i++) { for(j=i+1; j<(n-2); j++) { for(k=j+1; k<(n-1); k++) { for(h=k+1; h<n; h++) { // printf("%d %d %d %d ",i,j,k,h); ans=max(ans,get_num(0,i)+get_num(i,j)-get_num(j,k)*get_num(k,h)/get_num(h,n)); // printf("%lld ",ans); } } } } printf("%lld ",ans); continue; } for(i=0; i<n-4; i++) { sum1=sum1*10+s[i]-'0'; } for(i=1; i<=n-4; i++) { sum2=sum2*10+s[i]-'0'; } sum1+=s[n-4]-'0'; sum2+=s[0]-'0'; LL sum=max(sum1,sum2); printf("%lld ",sum+ans1); } return 0; }