220410总结
220410总结
总体分析
-
开题顺序:T1 - T3 - T2
-
T1和T3各花了半小时,T2花了两小时(还没做出来
-
T1最开始没考虑到先往左走再瞬移的情况,测样例的时候发现和结果差的太多,又重新想了想,发现了问题然后解决,再测发现两个样例都过了
(觉得应该是正解)于是就开下一题了 -
T3最开始想用差分数组存英雄身高(大概是脑子短路了想用差分但没想在哪用差分),但是发现每次查询都是 \(O(R)\) 的复杂度,在极端数据下应该是过不了的
于是就用差分数组存修改的信息(其实一开始就应该想到的),修改的复杂度是\(O(1)\),查询的复杂度是 \(O(R-L)\),大概能过?
测大样例发现 \(N=10^6,Q=1000\) 的时候就超时了。。。甚至吸氧都过不去
(大样例应该是格式不太对,我最后被迫用
char
型字符串读入的操作符,不然要么读到空格要么读到换行符但是因为我也不会更优的算法
(简而言之:太菜了),所以就扔了个快读上去好家伙快读一上直接快了将近一秒(
我
单方面宣布快读是神!upd. 看了队友博客我甚至怀疑我们做的是不是一套题(
upd. 在洛谷测了一下T1,发现调试时候的一个
printf
忘删了,,,upd. 在洛谷测了一下T3 发现不开O2会WA一个点TLE两个点,开了O2会TLE一个WA一个,,
upd. 最终是 \(0+20+100\)
-
T2想了各种奇怪的思路但是都很容易举出反例(想了一个半小时),最后想碰碰运气
(还没写完,先求最长上升子序列,再把不在这个序列里面的高度要么加要么减使它能放到序列里面T2能得多少分只能看数据了
-
时间分配还行,T2做得稍微有点急躁了,要是心静一点可能能想出来更好的方法
-
尽可能地一遍写对,debug太痛苦了
T1 catchcow
当动态规划做的
由于到达 \(i(1\leq i \leq N)\) 的最短时间一定是 \(N-i\) ,预处理出 \(f(i)=N-i(1\leq i \leq N)\)
然后对于点 \(i(N\leq i \leq K)\) ,它可以由 \(i-1\) 或 \(i+1\) 或 \(\dfrac{i}{2}(i=2n,n\in Z)\) 转移得到
然后T飞了。。。写的时候忘了可以瞬移 - 左移 - 瞬移这么走
所以对于这种最短步数之类的问题,应该优先考虑广搜
从一个点出发,第一次到达终点的步数一定是最少的
#include<bits/stdc++.h>
using namespace std;
struct S{
int d,s;
};
int vis[2000005];
int N,K;
int main(){
freopen("catchcow.in","r",stdin);
freopen("catchcow.out","w",stdout);
scanf("%d%d",&N,&K);
queue<S>q;
q.push((S){N,0});
while(true){
S t = q.front();
q.pop();
if(vis[t.d]) continue;
vis[t.d] = 1;
if(t.d == K){
return 0 & printf("%d\n",t.s);
}
if(t.d-1 >= 0) q.push((S){t.d-1,t.s+1});
if(t.d <= K){
q.push((S){t.d+1,t.s+1});
q.push((S){t.d*2,t.s+1});
}
}
return 0;
}
T2 grading
考试没做出来,考完看了一些题解
是个线性dp
显然修改高度是修改为原数组中的高度是最优的
设 \(f(i,j)\) 表示前 \(i\) 个数,末尾改成第 \(j\) 小的数的最小代价
可得状态转移方程 \(f(i,j)=\min(f(i,j-1),f(i-1,j)+\operatorname{abs}(A_i-B_i))\)
\(A_i\) 指原数组, \(B_i\) 指排序过的数组
这是改成单调不降所需的最小代价,单调不升同理
T3 magic
我的做法是用差分数组记录区间修改情况,查询的时候扫一遍 \([L,R]\) 整个区间
整体复杂度略高,不过堪堪通过评测(洛谷上的还过不去)
#include<bits/stdc++.h>
using namespace std;
int P[1000020];
int mA[1000020];
int N,Q;
inline int read() {//快读就是神!
register int x=0,f=1;
register char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
int main(){
freopen("magic.in","r",stdin);
freopen("magic.out","w",stdout);
N = read();Q = read();
for(int i = 1;i<=N;i++) P[i] = read();
char S[2];
while(Q--){
char md;
int l,r,d;
scanf("%s",S);
md = S[0];
l = read();r = read();d = read();
if(md == 'M'){
mA[l]+=d;
mA[r+1]-=d;
}else{
int ad = 0;
int cnt = 0;
for(int i = l;i<=r;i++){
ad += mA[i];
if(P[i] + ad >= d) cnt++;
}
printf("%d\n",cnt);
}
}
return 0;
}