luogu P3407 walk solving report

 

Title Description

 

On the road, the location is represented by the integer A.

When A = 0, there is a palace. When A> 0, there is east of A meters from the palace, when A <0, A is to have meters from the west palace.

On the road, there are N dwelling from west to east with a 1-N to label. Each house has a person. Residential only exist in an even integer points.

The king of the country believes that national physical decline, it is necessary to take more exercise, so the command must all go for a walk. All citizens, one second to go 1 meter. Each respective nationals to go east or west. These directions you know. After issuing the command to leave the house while everyone began to walk.

However, nationals of a country is very talkative, walking in the way if two people meet, they will stop and talk. People are walking across people who have stopped (overlap) also stopped to talk. Once stopped, we will talk to the incredibly hard, forget the walk.

Now the command has issued a T seconds, the state-owned Q important man, the king wanted to hold their position. Can you help him answer it?

 

Input Format

 

The first row is an integer of 3, N, T, Q

Next N lines of two integers Ai, Ri. Ai is the home of the coordinates, if Ri is 1, then will go east, if it is 2, to the west. Ai is the guaranteed data in ascending order, and there will be two initial positions coincide.

Next Q lines, each an integer that represents an important figure in the King concern.

 

Output Format

 

Q lines, each an integer that represents the person's coordinates.

 

20% Data N <= 100, T <= 10000

Further data 20% N <= 5000

In addition 20% of all data from several west from the west to the east several consecutive national all the rest

Data Ai is even 100%, | Ai | <= 10 ^ 18, | T | <= 10 ^ 18,1 <= Q <= N <= 100000.

I'm dividing line ------ ---------------------------------------- -------------------------------------------------- -------

Side effect problems: there are n number of individual shaft, a moving distance per second given direction (east or west) is, after a person when they encounter with a person does not move, seeking t seconds, the specified m the position of the individual is located.

This question is to see at first glance, it is estimated that you should have come up with a positive solution, positive solution of this problem should be more of miss.

For every person walking (to go west for example), the final stop no more than three cases:

1, time is up, you can not go any farther.

2, and their own people walk west to east met.

3, it was his own west met, he was dealing with people who meet.

For most of the west towards the west, you can not control him.

Similarly we can determine who to go east. Category talk on the line.

The time complexity of O (N).

Pasting the code is easy to understand:

 

#include<bits/stdc++.h>

#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)

using namespace std;

typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, Q, q[N];
long long ans[N], p[N][2], t;
inline ll read(){
    ll x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
    while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}
    return x*f;
}
int main(){
    n = read(); t = read(); Q = read();
    rep(i, 1, n) p[i][0] = read(), p[i][1] = read();
    rep(i, 1, Q) q[i] = read();     
    rep(i, 1, n)
        if(p[i][1] == 2){
            if(i == 1)
                ans[i] = p[i][0] - t;
            else if(p[i-1][1] == 2)
                ans[i] = max(ans[i-1], p[i][0]-t);
            else ans[i] = max(p[i][0]/2+p[i-1][0]/2, p[i][0]-t);
        }
    per(i, n, 1)   
        if(p[i][1] == 1){
            if(i == n)
                ans[i] = p[i][0]+t;
            else if(p[i+1][1] == 1)
                ans[i] = min(ans[i+1], p[i][0]+t);
            else ans[i] = min(p[i][0]/2+p[i+1][0]/2, p[i][0]+t);
        }
    rep(i, 1, Q) printf("%d\n", ans[q[i]]);
    return 0;
}
View Code

 

 

However, this is not the point, this question also O (N logN) in a non-positive solutions practice, constant giant small, positive solution to run faster than the above O (N)!

Ideas: a preprocessing of each meeting point, and when the position or + -t, to see whether the nearest meeting point, if it outputs the meeting point, or otherwise the output pos + t pos-t nearest point may encounter. binary search, details a little more, need extra attention.

code:

#include<bits/stdc++.h>

#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)

using namespace std;

typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
const ll inf = 4557430888798830399;
ll n, t, q;
ll s[N], k = 0;
struct people{ll pos, dic, id; } a[N];
bool mycmp(people a, people b) {return a.pos < b.pos; }
inline ll read(){
    ll x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
    while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}
    return x*f;
}
int main(){
    n = read(); t = read(); q = read();
    rep(i, 1, n) a[i].pos = read(), a[i].dic = read(), a[i].id = i;
    sort(a+1, a+n+1, mycmp);
    rep(i, 2, n){
        if(a[i].dic == 2 && a[i-1].dic == 1) s[++k] = (a[i].pos+a[i-1].pos)>>1;
    }  
    s[0] = -inf, s[k+1] = inf;
    rep(i, 1, q){
        ll x = read();
        ll posx = a[a[x].id].pos, flag = a[a[x].id].dic;
        ll l = 1, r = k, mid;
        while(l < r){
            mid = (l+r)>>1;
            if(flag == 1){
                if(s[mid] < posx) l = mid+1;
                if(s[mid] > posx) r = mid;
            }
            if(flag == 2){
                if(mid == l) mid++;
                if(s[mid] < posx) l = mid;
                if(s[mid] > posx) r = mid-1;
            }
        }
        mid = l;
        if(s[mid] < posx && flag == 2){
            if(s[mid+1] < posx && s[mid+1] != inf) mid++;
        }
        if(s[mid] > posx && flag == 1){
            if(s[mid-1] > posx && s[mid-1] != inf) mid--; 
        }
        if(flag == 1){
            if(s[mid] > posx+t && s[mid] > posx) printf("%lld\n", posx+t);
            else if(s[mid] < posx) printf("%lld\n", posx+t);
            else if(s[mid] < posx+t && s[mid] > posx) printf("%lld\n", s[mid]);
            else printf("%lld\n", s[mid]);
        }
        if(flag == 2){
            if(s[mid] < posx-t && s[mid] < posx) printf("%lld\n", posx-t);
            else if(s[mid] > posx-t && s[mid] < posx) printf("%lld\n", s[mid]);
            else if(s[mid] > posx) printf("%lld\n", posx-t); 
            else printf("%lld\n", s[mid]);
        }
    }
    return 0;
}
View Code

好了,这道题就这么愉快地结束了。

Guess you like

Origin www.cnblogs.com/smilke/p/11533230.html