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;
}
posted @ 2022-04-10 11:29  Burnling  阅读(46)  评论(0编辑  收藏  举报