P1081 开车旅行

 P1081 开车旅行

输入样例#1: 复制
4 
2 3 1 4 
3 
4 
1 3 
2 3 
3 3 
4 3
输出样例#1: 复制
1 
1 1 
2 0 
0 0 
0 0 
输入样例#2: 复制
10 
4 5 6 1 2 3 7 8 9 10 
7 
10 
1 7 
2 7 
3 7 
4 7 
5 7 
6 7 
7 7 
8 7 
9 7 
10 7
输出样例#2: 复制
2 
3 2 
2 4 
2 1 
2 4 
5 1 
5 1 
2 1 
2 0 
0 0 
0 0

 

题解:一道不可做的题;代码+思维
双向链表,倍增维护次大值最大值
https://www.luogu.org/problemnew/solution/P1081
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M = 1e5 + 5, P = 19;
struct edge{int l, r;}lnk[M];
struct node{
    int id, h;
    bool operator < (const node &rhs) const{
        return h < rhs.h;
    }
}p[M];
int rnk[M], nxta[M], nxtb[M], A, B, stA[M][P+1], stB[M][P+1], f[M][P+1];
inline bool dir(int t){
    if(!lnk[t].l)return 0;
    if(!lnk[t].r)return 1;
    if(p[t].h - p[lnk[t].l].h <= p[lnk[t].r].h - p[t].h)return 1;
    return 0;
}
inline int pd(int t, int a, int b){
    if(!a || !b)return p[a + b].id;
    if(p[t].h - p[a].h <= p[b].h - p[t].h) return p[a].id;
    return p[b].id;
}
inline int ab(int a, int b){return a >= b ? a - b : b - a;}

void drive(int st, int lim){
    A = 0, B = 0;
    int tmp = lim;
    for(int o = P; o >= 0; o--)
        if(f[st][o] && (long long) A + B + stA[st][o] + stB[st][o] <= tmp)
            A += stA[st][o], B += stB[st][o], st = f[st][o];
    if(nxta[st] && A + B + stA[st][0] <= tmp) 
        A += stA[st][0];
}
int read(){
    int x = 0; int f = 1; char c = getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
    return x*=f;
}

int main(){
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) p[i].h = read(), p[i].id = i;
    sort(p + 1, p + 1 + n);
    for(int i = 1; i <= n; i++) rnk[p[i].id] = i;
    for(int i = 1; i <= n; i++) lnk[i].l = i - 1, lnk[i].r = i + 1;
    lnk[1].l = 0, lnk[n].r = 0;
    for(int i = 1; i <= n; i++) {
        int t = rnk[i];
        bool fg = dir(t);
        if(fg) nxtb[i] = p[lnk[t].l].id, 
        nxta[i] = pd(t, lnk[lnk[t].l].l, lnk[t].r);
        else nxtb[i] = p[lnk[t].r].id,
        nxta[i] = pd(t, lnk[t].l, lnk[lnk[t].r].r);
        if(lnk[t].r) lnk[lnk[t].r].l = lnk[t].l;
        if(lnk[t].l) lnk[lnk[t].l].r = lnk[t].r;
    }
    for(int i = 1; i <= n; i++){
        f[i][0] = nxtb[nxta[i]];
        stA[i][0] = ab(p[rnk[nxta[i]]].h, p[rnk[i]].h);
        stB[i][0] = ab(p[rnk[f[i][0]]].h, p[rnk[nxta[i]]].h);
    }
    for(int o = 1; o <= P; o++)
        for(int i = n; i; i--){
            f[i][o] = f[f[i][o-1]][o-1];
            stA[i][o] = stA[i][o-1] + stA[f[i][o-1]][o-1];
            stB[i][o] = stB[i][o-1] + stB[f[i][o-1]][o-1];
        }
    int X0 = read();
    double tmp = 2e9;
    int id = -1;
    for(int i = 1; i <= n; i++){
        drive(i, X0);
        if(B && 1.0*A/B < tmp){
            tmp = 1.0*A/B; id = i;
        }
        else if(B && 1.0*A/B == tmp && rnk[i] > rnk[id]) id = i;
    }
    printf("%d\n",id);
    int m = read();
    while(m--){
        int st = read(), x = read();
        drive(st, x);
        printf("%d %d\n", A, B);
    }
    
}
View Code

 

 
posted @ 2018-11-04 17:33  Ed_Sheeran  阅读(223)  评论(0编辑  收藏  举报