说些感触。
= =、哎,说起来重现还真是好气啊。
出去的大二过去两题打铁,今天我们队边玩边打过了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\n");
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\n",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\n",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\n",tt);
}
// printf("%lf\n",tmp);
}
printf("Case #%d: ",cas++);
printf("%lld\n",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 \n",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\n",ans);
}
}
}
}
printf("%lld\n",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\n",sum+ans1);
}
return 0;
}