1 条题解

  • 0
    @ 2025-8-24 22:55:54

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar naturelyf
    > 最后在线时间:2025年7月24日8时49分 <

    搬运于2025-08-24 22:55:54,当前版本为作者最后更新于2024-11-12 16:54:02,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题外话

    建议评蓝,因为比 P9209

    解题思路

    首先看到 1n,m1051\le n,m \le10^5 ,所以解决每个查询的时间最多只有 lognlog{n} 的时间。我们可以发现,每次选择上山,都会额外花费一个 ss 的时间下山,而如果我们直接去将要去的那座山就会节约这个 ss ,所以我们会选择直接去最后要去的那座山也就是能呆的时间最长的那座山。

    代码实现

    首先看到 n,m1000n,m \le 1000 ,可以使用 n2n^2 的算法,具体实现就是对于每个询问都一一计算出最大值,代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 2e5 + 10;
    int n, m;
    struct node {
        int x, t, s;
        bool friend operator<(node a, node b) { return a.x < b.x; }
    } dt[N];
    int main() {
        freopen("vrsar.in", "r", stdin);
        freopen("vrsar.out", "w", stdout);
        cin >> n >> m;
        for (int i = 1; i <= n; i++) {
            int x, t, s;
            cin >> x >> t >> s;
            dt[i] = { x, t, s };
        }
        sort(dt + 1, dt + n + 1);
        while (m--) {
            int k;
            cin >> k;
            int ans = 0;
            for (int i = 1; i <= n; i++) ans = max(ans, dt[i].t - abs(dt[i].x - k));
            cout << ans << " ";
        }
        return 0;
    }
    

    这个代码可以通过 4444 分,也就是 63%63\% 的数据,所以需要优化,这里就衍生出两种做法,一种在线一种离线。

    离线做法

    可以发现滑雪时间 T=t[i]abs(x[i]d)T=t[i]-abs(x[i]-d) 所以分两段考虑,先给所有 dd 排序,在 dd 前面计算距离为 T=t[i]x[i]+dT=t[i]-x[i]+d 都有 t[i]x[i]t[i]-x[i] 所以考虑存这个东西,可以使用 setset 来快速实现,在 dd 后面的也同理,代码如下:

    #include<bits/stdc++.h>
    #define PII pair<int,int>
    #define wz first
    #define id second
    using namespace std;
    const int N=2e5+10;
    int n,m;
    struct node{
    	int x,t,s;
    	bool friend operator<(node a,node b){
    		return a.x<b.x;
    	}
    }dt[N];
    set<int> st,st1;
    PII qu[N];
    int ans[N];
    int main(){
    //	freopen("vrsar.in","r",stdin);
    //	freopen("vrsar.out","w",stdout);
    	cin>>n>>m;
    	for(int i=1;i<=n;i++){
    		int x,t,s;
    		cin>>x>>t>>s;
    		dt[i]={x,t,s};
    	}
    	st.insert(1e9+10);
    	st1.insert(1e9+10);
    	sort(dt+1,dt+n+1); 
    	for(int i=1;i<=n;i++)
    		st.insert(-(dt[i].t-dt[i].x));
    	for(int i=1;i<=m;i++){
    		cin>>qu[i].wz;
    		qu[i].id=i;
    	}
    	sort(qu+1,qu+m+1);
    	for(int i=1,j=1;i<=m;i++){
    		while(dt[j].x<=qu[i].wz&&j<=n){
    			st.erase(-(dt[j].t-dt[j].x));
    			st1.insert(-(dt[j].t+dt[j].x));
    			j++;
    		}
    		ans[qu[i].id]=max(-*st.begin()+qu[i].wz,-*st1.begin()-qu[i].wz);
    	}
    	for(int i=1;i<=m;i++)cout<<ans[i]<<" ";
    	return 0;
    }
    //瓶颈:找相减最大时间
    //63pts
    //如何优化? 
    //t=dt[i].t-abs(dt[i].x-k)
    //t=dt[i].t-dt[i].x+k(dt[i]>k)
    //t=dt[i].t+dt[i].x-k(dt[i]<k)
    //set优化nlogn
    //100pts
    
    在线做法

    同样的思路,关键在于快速查询,看到区间,看到最大值,看到 lognlog{n} 考虑线段树,但是十分繁琐,打了半小时没打出来放弃了 错误代码 ,也不知道会不会有人这么写。

    • 1

    信息

    ID
    9871
    时间
    1000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者