zoukankan      html  css  js  c++  java
  • [NOIP2012] 开车旅行

    [NOIP2012] 开车旅行

    题目大意:在数轴上有(n)个不同高度的城市从西到东排列,定义(dis(i,j))(i)城市到(j)城市的(abs(h_i,h_j)),有两个人(A)(B)轮流开车从任意城市出发向东旅行,(A)一定是先开车的,他会选择去距离当前城市第二近的城市((dis)一样,去高度低的城市),走一定的里程,那么第二次(B)在开车,他会选择去距离当前的城市最近的城市((dis)一样,去高度低的城市),走一定的里程;如果对于(A,B)里程不够了,或者没有可以选的城市了,结束旅行.现在有两个询问

    1. 无论从哪个地方出发,给定里程数,求(A,B)开车里程的最小比值所在的旅行的出发地,如果有多个出发地的比值相同,取海拔高的
    2. 给定(m)组询问(S_i,X_i),求从(S_i)出发,不能超过(X_i)的里程的旅行中,(A)(B)分别走过的里程值

    Solution.70pts

    数据范围比较小,模拟可过,不要什么图都拿邻接表存,然后我的深搜就写挂了

    Code.70pts

    一些操作还是很巧妙的

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    
    const int N = 1005;
    
    int n, x0;
    int h[N], dis[N][N], one[N], two[N];
    //学一下自己写abs
    int main(){
    	scanf("%d", &n);
    	for(int i = 1; i <= n; ++i) scanf("%d", &h[i]);
    	for(int i = 1; i <= n; ++i){
    		for(int j = i + 1; j <= n; ++j){
    			dis[i][j] = abs(h[i] - h[j]);
    			if(!one[i]){
    				one[i] = j;
    			}else if(dis[i][one[i]] > dis[i][j] || (dis[i][one[i]] == dis[i][j] && h[one[i]] > h[j])){
    				two[i] = one[i];
    				one[i] = j;
    			}else if(!two[i]){
    				two[i] = j;
    			}else if(dis[i][two[i]] > dis[i][j] || (dis[i][two[i]] == dis[i][j] && h[two[i]] > h[j])){
    				two[i] = j;
    			}
    		}
    	}
    	int x, a, b, c, ans;
    	scanf("%d", &x);
    	double tmp = 2147483647;
    	for(int i = 1; i <= n - 2; ++i){//n - 1 和 n 的旅程还没开始就结束了
    		a = b = 0;
    		c = i;
    		for(int j = 1; ; ++j){
    			if(j & 1){
    				if(!two[c] || dis[c][two[c]] + a + b > x) break;
    				a += dis[c][two[c]], c = two[c];
    			}else{
    				if(!one[c] || dis[c][one[c]] + a + b > x) break;
    				b += dis[c][one[c]], c = one[c];
    			}
    		}
    		if(b && a * 1.0 / b < tmp) tmp = a * 1.0 / b, ans = i;
    		else if(b && a * 1.0 / b == tmp){
    			if(h[ans] < h[i])
    				ans = i;
    		}
    	}
    	printf("%d
    ", ans);
    	int m; 
    	scanf("%d", &m);
    	while(m--){
    		scanf("%d %d", &c, &x);
    	  	a = b = 0;
    		for(int j = 1; ; ++j){
    			if(j & 1){
    				if(!two[c] || dis[c][two[c]] + a + b > x) break;
    				a += dis[c][two[c]], c = two[c];
    			} else {
    				if(!one[c] || dis[c][one[c]] + a + b > x) break;
    				b += dis[c][one[c]], c = one[c];
    			}
    		}
    		printf("%d %d
    ", a, b);
    	}
    	return 0;
    }
    

    Solution.100pts

    排序后运用双向链表(O(n))处理(one[i])(two[i]),链表上的序号就代表了排序后的城市排名

    为了方便,直接把(i-1,i+1,i-2,i+2)排序取前两名,然后倍增的搞,转移也方便

    Attention.100pts

    • (prepare)函数按照相对值的绝对值排序
    • 双向链表里面删去结点,注意要直接将前驱后继连接,不可以变成(i-1)(i+1),因为很可能(i-1)(i+1)也是一个被删除的点
    • 十分注意快读中位运算的优先级

    Code.100pts

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define pf(x) printf("%d
    ", x)
    using std::sort;
    
    const int N = 1e5 + 10;
    
    int n;
    int pre[N], nxt[N], head[N], one[N], two[N], data[N];
    int A[N][22], B[N][22], f[N][22];
        
    int abs(int x) {
        if (x >= 0) return x; return -x;
    }
        
    struct City{
        int p, i;
        bool operator < (const City &cmp) const {
            return p < cmp.p;
        }
    }h[N];
    
    struct QWQ{
        int p, i;
        bool operator < (const QWQ &cmp) const {
            if(p == cmp.p){
                return data[i] < data[cmp.i];
            }
            return p < cmp.p;
        }
    };
    
    inline int read(){
        int x = 0, f = 1;
        char c = getchar();
        while(c < '0' || c > '9'){
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9'){ 
            x = (x << 3) + (x << 1) + (c ^ 48);//不括起来就出现了傻逼现象 
            c = getchar();
        }
        return x * f;
    }
    
    inline void get_dis(int af, int bf){
        QWQ qwq[5];
        int qwq_cnt = 0;
        if(pre[af]) {
            qwq[++qwq_cnt].p = abs(h[pre[af]].p - data[bf]);
            qwq[qwq_cnt].i = h[pre[af]].i;
            if(pre[pre[af]]){
                qwq[++qwq_cnt].p = abs(h[pre[pre[af]]].p - data[bf]);
                qwq[qwq_cnt].i = h[pre[pre[af]]].i;
            }
            nxt[pre[af]] = nxt[af];//delete
     	}
        if(nxt[af]){
            qwq[++qwq_cnt].p = abs(h[nxt[af]].p - data[bf]);
            qwq[qwq_cnt].i = h[nxt[af]].i;
            if(nxt[nxt[af]]){
                qwq[++qwq_cnt].p = abs(h[nxt[nxt[af]]].p - data[bf]);
                qwq[qwq_cnt].i = h[nxt[nxt[af]]].i;
            }
                
            pre[nxt[af]] = pre[af];//delete pre[nxt[af]] = af - 1;
        }
        sort(qwq + 1, qwq + qwq_cnt + 1);
        if(qwq_cnt >= 1)one[bf] = qwq[1].i;
        if(qwq_cnt >= 2)two[bf] = qwq[2].i;
        return;
    }
    
    inline void prepare(){
        for(int i = 1; i <= n; ++i){
            if(two[i]) A[i][0] = abs(data[two[i]] - data[i]);
            if(one[two[i]]) B[i][0] = abs(data[one[two[i]]] - data[two[i]]);
            if(one[two[i]])f[i][0] = one[two[i]];
        }
    }
    
    int main(){
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i){
            h[i].p = read();
            h[i].i = i;
            data[i] = h[i].p;
        }
        sort(h + 1, h + n + 1);
        for(int i = 1; i <= n; ++i){
            head[h[i].i] = i;
            nxt[i] = i + 1;
            pre[i] = i - 1;
            if(i == n)
                nxt[i] = 0;
        }
        for(int i = 1; i <= n; ++i)
            get_dis(head[i], i);
        prepare();
        for(int i = 1; i <= 17; ++i){
            for(int j = 1; j <= n; ++j){
                A[j][i] = A[j][i - 1] + A[f[j][i - 1]][i - 1];
                B[j][i] = B[j][i - 1] + B[f[j][i - 1]][i - 1];
                f[j][i] = f[f[j][i - 1]][i -1];
            }
        }
        int x0, a, b, c, z, ans;
        double tmp = 2147483640;
        
        scanf("%d", &x0);
        for(int i = 1; i <= n; ++i){
            a = b = 0, z = x0, c = i;
            for(int j = 20; j >= 0; --j){			
                if(f[c][j] && z >= A[c][j] + B[c][j]){
                    a += A[c][j];
                    b += B[c][j];
                    z -= A[c][j] + B[c][j];
                    c = f[c][j];
                }
            }
            if(A[c][0] <= z) a += A[c][0];
            if(b && a * 1.0 / b < tmp) {
                tmp = a * 1.0 / b, ans = i;
            }
            else if(b && a * 1.0 / b == tmp){
                if(data[ans] < data[i])
                    ans = i;
            }
        }
        printf("%d
    ", ans);
        int m;
        scanf("%d", &m);
        while(m--){
            scanf("%d %d", &c, &x0);
            z = x0, a = b = 0;
            for(int j = 20; j >= 0; --j){			
                //printf("c = %d j = %d f[c][j] = %d  z = %d a[c][j] = %d b[c][j] = %d 
    ", c, j, f[c][j], z, A[c][j], B[c][j]);
                if(f[c][j] && z >= A[c][j] + B[c][j]){
                    a += A[c][j];
                    b += B[c][j];
                    z -= A[c][j] + B[c][j];
                    c = f[c][j];
                }
            }
            if(A[c][0] <= z) a += A[c][0];
            printf("%d %d
    ", a, b);
        }
        return 0;
    }
    
  • 相关阅读:
    stenciljs 学习四 组件装饰器
    stenciljs 学习三 组件生命周期
    stenciljs 学习二 pwa 简单应用开发
    stenciljs ionic 团队开发的方便web 组件框架
    stenciljs 学习一 web 组件开发
    使用npm init快速创建web 应用
    adnanh webhook 框架 hook rule
    adnanh webhook 框架 hook 定义
    adnanh webhook 框架request values 说明
    adnanh webhook 框架execute-command 以及参数传递处理
  • 原文地址:https://www.cnblogs.com/LMSH7/p/9605605.html
Copyright © 2011-2022 走看看