7.31日考试记录
机房模考:2019.7.31
今天这套题和昨天的是一套(Day2),但是题目难度大大增加。
还是三道题目的题量,但是第三题表示根本做不动23333333
由于实在是太恶心做不动菜是原罪,本人又在考试的时候写了记录233
所以半引用半写吧
1. Count
"和昨天一样,是一道数学问题。很简单的模拟,由于数据上了200000,单纯地顺序查找是跑不过的。
于是很容易想到二分查找嘛233
排序一手,然后二分。最需要注意的就是好感度这个东西是要大于S的
我就是被这么卡了一会2333"
好吧其实这题还能用桶写,而且是真的O(n),跑出飞毛腿的速度,虽然加了优化的二分O(nlog2n)也就相当于带了一个很小的常数,但毕竟还是慢一点点嘛2333333
Code:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=200005;
int l,r,n,s,mid,a[MAXN];
long long ans=0;
bool cmp(int x,int y){
return x>y;
}
int main(){
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
scanf("%d%d",&n,&s);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n,cmp);
l=0,r=n-1;
for(int i=0;i<n;i++){
int req=s-a[i]+1; l=i+1;
while(mid=(l+r)/2,l<=r){
if(a[mid]>=req) l=mid+1;
else if(a[mid]<req) r=mid-1;
}
ans+=(l-i)-1,r=mid;
}
printf("%lld",ans);
return 0;
}
2.jogging
"又乍一看,负权单源最短路,SPFA跑一手。
一看数据最短路根本跑不过233
但是有一个与最短路不一样的在于它只能向高的凉亭跑。
跑的顺序有限制证明可以用另外一种方法去跑2333
上一手DAG上DP。
写起来挺好写的,后序遍历到n,然后倒推,状态就设一个节点位置,
然后转移就是节点所有可以去到的点的答案加上连接两个点的边的权值的最小值咯"
(写自考场)
但是其实这道题跑SPFA可以过23333333
双向队列优化的SPFA应该是可以勉强过掉这一题的,像我们机房有写Bellman-ford的也有直接裸SPFA的,居然还有一个裸的也过了233,但是也有SPFA40分的2333333333333333。人穷常数大
Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100005;
int siz[MAXN],n,ml,md,a,b,c,f[MAXN];
char tobe_or_nottobe[2][5]={"YES","NO"};
struct edge{
int value;
int to;
}tmp;
vector <edge> q[MAXN];
int dp(int u){
if(f[u]!=INT_MAX) return f[u];
siz[u]=q[u].size();
for(int i=0;i<siz[u];i++)
f[u]=min(f[u],dp(q[u][i].to)+q[u][i].value);
if(u==n) f[u]=0;
return f[u];
}
int main(){
freopen("jogging.in","r",stdin);
freopen("jogging.out","w",stdout);
scanf("%d%d%d",&n,&ml,&md);
fill(f,f+n+1,INT_MAX);
for(int i=0;i<ml;i++){
scanf("%d%d%d",&a,&b,&c);
tmp.value=c,tmp.to=max(a,b);
q[min(a,b)].push_back(tmp);
}
for(int i=0;i<md;i++){
scanf("%d%d%d",&a,&b,&c);
tmp.value=-c,tmp.to=max(a,b);
q[min(a,b)].push_back(tmp);
}
printf("%d\n%s",dp(1),tobe_or_nottobe[(dp(1)>=0)]);
return 0;
}
3.Cube
"这道题个人评级紫题吧233
想a掉这题实在难(这不是你连部分分都懒得写的理由),而且其实就算是写大暴力其实也挺麻烦,一个立方体的模拟很难用一个公式去表示它的运动。也许可以,但我太弱,推不动233(菜是原罪)
我有两个思路,可惜都打不出来
第一个,直接跑dp。但是如果要在这题里免除后效性,至少要开一个坐标(二维)并记录底面和另一个面(必须不为底面的对面)四个属性。
而题目给的是多组数据,所以处理x1,x2的时候可以用一些别的方法比如处理一个相对坐标(虽然并不严谨因为可能路径会出现先往上或者往左绕的情况)。但是好像直接再开一维(一重循环)也能跑的过,所以f数组可能还要另外一维,数据
所以就有五维了23333。
状态的转移也很麻烦。首先,在一个位置上的运动就有6(另一面)*6(底面)*4(上下左右)种,翻转的操作也不知咋写。前面说了,立方体运动的公式反正我没推出来,所以只能写他个十几行去模拟(真的没耐心所以才放弃了)
总而言之,我写不出
第二个,建图跑一手dijkstra。
如果是堆优化的dijksta应该是跑得过数据的。实现的难度肯定不亚于dp。
首先它的点也需要四个维度的状态记录,所以点数应该是nn6*6的。
建图的话就是说将隔壁而且能够跑出来的状态给连上给个权值。比如现在的底面是正方形的下面,右面就是右面,那么它可以跑成底面为右面,右面为上面等等四种情况,都要连上边2333,然后就是从头开始跑一遍dijkstra。emmmmm,具体时间我也没算,应该是O(n2*log2(n2))级别的算法(只是带了个很大的常数嘛233)。"
(写于考场)
看来我还是有点聪明的。
这道题确实是要拆点再跑最短路,而且骰子的状态不仅可以用两维存,还可以直接用类似于康托展开的方式存下。
给的正解是拆点加SPFA,不知道为什么老师并没有说其他单源最短路的做法可不可以,但众所周知,关于SPFA,它死的总是比Dijkstra早,在无负权的图里,应该是可以跑Dijkstra的咯
但是一个骰子立方体的模拟还是好难好难好难好难好难233
所以还是贴上老师给的标程吧写不出啊太菜了233
Code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll c[4][6]={{0,1,5,2,3,4},
{4,2,0,3,1,5},
{0,1,3,4,5,2},
{2,4,1,3,0,5}};
const ll state[25]={0,123456,124563,125634,126345,
213654,214365,215436,216543,
351624,352416,354162,356241,
461325,462513,463251,465132,
531426,532614,534261,536142,
641523,642315,643152,645231};
const ll dx[4]={1,0,-1,0};
ll dy[4]={0,1,0,-1};
const ll maxn=200;
const ll size=maxn*maxn*24;
struct node{
ll x,y,k;
ll a[10];
};
ll dis[maxn][maxn][25];
bool v[maxn][maxn][25];
node q[size];
ll sx,sy,ex,ey,k;
ll head,tail,n,ans,test;
ll d[10],t[10];
void init()
{
cin>>n>>test;
for (int i=0 ;i<6;i++) cin>>d[i];
}
ll number (){
ll x ;
x=0;
for (int i=0 ;i< 6 ;i++)
x=x*10+(t[i]+1);
for (int i=1 ;i<= 24 ; i++)
if (x==state[i])
return i;
}
void bfs()
{
ll i,j;
node now,tmp;
head=0; tail=1;
memset(dis,0x3f,sizeof(dis));
q[1].x=sx; q[1].y=sy; q[1].k=1;
for (int i=0 ;i< 6 ;i++ )
q[1].a[i]=i;
dis[sx][sy][1]=d[4];
memset(v,0,sizeof(v));
while (head<tail)
{
head=head+1;
now=q[head];
for (int i=0 ;i< 4;i++)
{
tmp.x=now.x+dx[i];
tmp.y=now.y+dy[i];
if (tmp.x<1 || tmp.x>n) continue;
if (tmp.y<1 || tmp.y>n) continue;
for (int j=0 ;j<6; j++) t[j]=now.a[c[i][j]];
k=number();
if (dis[tmp.x][tmp.y][k]>dis[now.x][now.y][now.k]+d[t[4]])
{
dis[tmp.x][tmp.y][k]=dis[now.x][now.y][now.k]+d[t[4]];
if (!v[tmp.x][tmp.y][k])
{
v[tmp.x][tmp.y][k]=true;
tail=tail+1;
q[tail].x=tmp.x; q[tail].y=tmp.y;
q[tail].k=k;
for(int i=0;i<6;i++)
q[tail].a[i]=t[i];
}
}
}
v[now.x][now.y][now.k]=false;
}
ans=0x3f3f3f3f;
for (int i=1 ;i<= 24;i++)
if (dis[ex][ey][i]<ans) ans=dis[ex][ey][i];
}
void solve()
{
for (int i=1 ;i<=test;i++)
{
cin>>sx>>sy>>ex>>ey;
bfs();
cout<<ans<<endl;
}
}
int main()
{
freopen("cube.in","r",stdin);
freopen("cube.out","w",stdout);
init();
solve();
return 0;
}
"离下考还有十分钟。本人混吃等死,看着旁边的clk大佬一点一点优化最后一题暴力:
woc,他怎么暴力跑出正解速度了???
最后一题测这么大数据0.05s???
woc太强了%%%
STO Clk Orz OTZ %%%
哎,其实我这种也是缺少耐心的一种表现,只要一打难一点的模拟就没有半点耐心。稍微有点思维难度的暴力就不想去打打骗分。虽然确实菜到不一定打得对,但是这确实是一个硬伤啊
不得不说得学习clk大佬这种精神Orz
不说多的,下课打一手山东OI猪国杀练一练吧少年(逃)"
(写于考场)
虽然clk最后还是挂了2333
但是确实,这是我一个弱点,前一段时间这方面的问题出的也不少。要磨性子啊233