2024.11.02模拟赛( — _ — )
挂了至少30分!!不——开——心——
钢哥说,大家要休息好,于是模拟赛晚点,变成了3小时3道题。T1打的正解(但没调出来版),T2T3打的暴力(但全挂了版),预计总分120+,但实际总分80。
小小总结一下:昨晚多睡了一小时,今天思路确实感觉更清晰了(但也有可能是因为题目不难……)。但今天时间没分配好。我照常第一个小时把所有题看一遍,深入思考T1+打后两题暴力,两眼一抬,一个小时再次没了。若是T3T4暴力分(期望55)都拿到了那还好,但是全挂了,相当于白白浪费一小时。接着两个小时,忘了咋分配的了,好像还分了点时间又去搞T2,最后大概只有一个多小时的时间去写、去调T1。外加今日T1代码尤其长,这一个小时是极其紧张的————然后就成功挂掉20分。
所以,下次一定要在40分钟内打完后面大题的暴力并思考T1T2,每做完一道题出去换换脑子,回来全神贯注做手上的题,不要再去想刚刚打完的暴力。同时,思考时一定要严谨!科学!准确!模拟赛时没有多少时间来让我调各种纸张错误,只能在敲代码的时候就注意细节、边界等等。我的代码能力实在是难以信任。
T1【秋秋飞车】
题目大意:
忘了 给出一个n个坐标为(x,y)、价值为w的点(1<=n,x,y<=2e5),接下来给出q个操作,每次操作给出方向d与距离v,每次移动可以获得路径上的价值和(包括终点不包括起点),问q次操作后的价值和(1<=n,x,y,v<=2e5)
解题思路:
一眼搜索。看到复杂度后,一眼不是搜索。又发现每次是要路径上的和,每次路径不是横着就是纵着,于是想到每一列、每一行前缀和,因为炸裂的复杂度而用vector存储。然后没了。然后炸了。
长长一坨代码
#incIude <bits/stdc++.h>
#define int long long
const int N=2e5+10;
using namespace std;
int n,q;
struct NODE { int x,y,w; }a[N];//记录点
struct node { int x,w; };//x值相当于普通前缀和数组的第二维
vector <node> sum1[N],sum2[N];//记录前缀和
int sx=1,sy=1;//看好起始点
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};//方向不要和题意搞反
int ans;
void read()
{
scanf("%lld%lld",&n,&q);
for (int i=1;i<=n;i++)
{
int x,y,w;
scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].w);
}
}
bool cmp1(NODE aa,NODE bb)
{
if (aa.x!=bb.x) return aa.x<bb.x;
return aa.y<bb.y;
}
bool cmp2(NODE aa,NODE bb)
{
if (aa.y!=bb.y) return aa.y<bb.y;
return aa.x<bb.x;
}
void init()//搞前缀和
{
sort(a+1,a+1+n,cmp1);
for (int i=1;i<=n;i++)
{
int x=a[i].x,y=a[i].y,w=a[i].w;
if (!sum1[x].size()) sum1[x].push_back((node){0,0});//防止越界
int sum=sum1[x][sum1[x].size()-1].w;
sum1[x].push_back((node){y,sum+w});
}
sort(a+1,a+1+n,cmp2);
for (int i=1;i<=n;i++)
{
int x=a[i].x,y=a[i].y,w=a[i].w;
if (!sum2[y].size()) sum2[y].push_back((node){0,0});
int sum=sum2[y][sum2[y].size()-1].w;
sum2[y].push_back((node){x,sum+w});
}
}
int fd(int x,int y,int k)//不会lower_bound,于是手搓 求sum[x]中第一个<=y的值的下标(k表前缀和类型)
{
if (k==0)
{
int l=0,r=sum1[x].size()-1;
while (l<r)
{
int mid=(l+r+1)/2;
if (sum1[x][mid].x<=y) l=mid;
else r=mid-1;
}
return r;
}
if (k==1)
{
int l=0,r=sum2[x].size()-1;
while (l<r)
{
int mid=(l+r+1)/2;
if (sum2[x][mid].x<=y) l=mid;
else r=mid-1;
}
return r;
}
}
int _abs(int aa)//手搓abs
{
if (aa>=0) return aa;
return -aa;
}
signed main()
{
read();
init();
while (q--)
{
int d,v;
scanf("%lld%lld",&d,&v);
int xx=sx+dx[d]*v,yy=sy+dy[d]*v;
if (d%2==1)//x上不变,y上前缀和
{
if (!sum1[xx].size())
{
sx=xx;
sy=yy;
continue;
}
int d1,d2;
if (yy<sy) d1=fd(xx,yy-1,0),d2=fd(xx,sy-1,0);//因为有“取终点不取起点”的限制,手模后发现不同走法前缀和取法还不一样
else d1=fd(xx,yy,0),d2=fd(xx,sy,0);
ans+=_abs(sum1[xx][d1].w-sum1[xx][d2].w);
}
if (d%2==0)//与上相同
{
if (!sum2[yy].size())
{
sx=xx;
sy=yy;
continue;
}
int d1,d2;
if (xx<sx) d1=fd(yy,xx-1,1),d2=fd(yy,sx-1,1);
else d1=fd(yy,xx,1),d2=fd(yy,sx,1);
ans+=_abs(sum2[yy][d1].w-sum2[yy][d2].w);
}
sx=xx;
sy=yy;
}
printf("%lld",ans);
return 0;
}
一切的一切都没问题,一开始我的想法没错,过程中也没有出关键性的大错误,但仍然在细节处理上出了岔劈。但要是跑样例出错时,我像我下午那样分别手模两种情况,我也不会没调出来的。只因调程序时只剩下了不到半小时,调程序时我完全无法沉下心来去想。
所以说,还是两点,一是时间规划不合理,二是细节处理不到位(老问题了)。所以说,还是得保证睡眠以保证清醒的脑子与思路,有了清醒的脑子才能全神贯注地去想题、去处理细节。感觉代码能力有提高,不管程度怎样,也算是一件好事。
T2T3不会不会,不写不写(题解怎么写的那么抽象啊——)