luogu P3407徒歩解決レポート

 

タイトル説明

 

道路上に、位置は、整数Aで表されます

場合A = 0は、宮殿があります。場合<0 A> 0は、宮殿からメートルの東がある場合、Aは、西宮殿からメートルを有することです。

道路で、Nは、ラベルに1-Nと西から東に住居があります。各家には人を持っています。住居は、偶数点に存在します。

国の王は国民の物理的な下落が、もっと運動を取ることが必要であると考えているので、コマンドはすべての散歩に行く必要があります。すべての市民は、1秒は1メートルを行きます。それぞれの国民は、東または西に行きます。これらの方向は、あなたが知っています。誰もが歩き始めながら家を残すためにコマンドを発行した後。

しかし、国の国民は、二人は、彼らが停止してお話します満たせば道を歩いて、非常におしゃべりです。人々はまた話を停止(重複)を停止している人たちの上を歩くされています。一度停止し、私たちは散歩を忘れて、信じられないほどハードに話をします。

今すぐコマンドがT秒、国有Q重要な男を発行している、王は自分の位置を保持したかったです。あなたは彼がそれに答えることはできますか?

 

入力形式

 

最初の行は3、N、T、Qの整数です。

二つの整数愛は、Rの次のNライン。愛は、Riが1であれば、それは2であれば、その後、西へ、東行きます、座標の家です。愛は昇順で保証されたデータであり、2つの初期位置が一致があるでしょう。

次のQライン、各キング懸念で重要な数値を表す整数。

 

出力フォーマット

 

Qライン、一人一人の座標を表す整数。

 

20%データN <= 100、T <= 10000

さらに、データの20%N <= 5000

いくつかの西からのすべてのデータの20%を西から東、いくつかの連続した国家のすべての残りの部分に加え、

あい| | <= 10 ^ 18、| T | <= 10 ^ 18,1 <= Q <= N <= 100000データAiが、さらに100%です。

私はラインを分割しています------ ---------------------------------------- -------------------------------------------------- -------

副作用の問題:個々のシャフトのn個、第二所定の方向(東または西)であり、これらはt秒を求めて、移動しない人と出会う人後に、指定されたm個あたりの移動距離があります個々の位置が位置しています。

この質問は、最初の一目で確認することです、それはあなたが肯定的な解決策が出ているべきであると推定され、この問題の正の解は、ミスのよりでなければなりません。

(例えば西行き)歩いてすべての人、最後のピットストップを超えない3例の場合:

図1は、時間がアップして、あなたはどんな遠くに行くことはできません。

2、そして自分自身の人々は東に西に会っ歩きます。

図3は、それは彼自身の西は、彼が出会った人を扱った、会いました。

西への西のほとんどは、あなたは彼を制御することはできません。

同様に、私たちは東に行くために誰かを決定することができます。ライン上のカテゴリーの話。

Oの時間複雑度(N)。

コードを貼り付けると、理解しやすいです。

 

#include <ビット/ STDC ++ H> の#defineは長い長いっ
 の#define融点make_pair用
 の#define REPは(iは、、B)は、(i ++は; iが=(B)<I =(A)INT)のため
 の#defineを(パーI、B)(iは(A = INT)のために、I> =(B); i--)使用して名前空間STDを、
typedefのペア < int型int型 > PII。
typedefをダブルデシベル。
CONSTのINT N = 1E6 + 50 INTのN、Q、Q [N]。
長い長い ANS [N]、P [N] [ 2 ]、T。
インライン読み取り11(){ 
    LL、X = 0、F = 1



 
  ;
    チャー CH = GETCHAR()。
    一方、(CH < ' 0 ' || CH> ' 9 '){ 場合(CH == ' - ')、F = - 1CH = GETCHAR();}
     一方(CH> = ' 0 ' && CH <= ' 9 '){X =(x << 3)+(X << 1)+(CH ^ 48)。CH = GETCHAR();}
     戻りのx *のF。
} 
int型のmain(){ 
    N)=(読み取り; T =読み取ります(); Q =読む(); 
    担当者(I、1、n)はP [I] [ 0 ]読み取り=()、P [I] [ 1 ] = 読み取ります(); 
    担当者(I、1、Q)Q [I] = (読み取り)     
    担当者(I、1 、n)の
         場合(P [I] [ 1 ] == 2 ){
             場合(I == 1 
                ANS [I] = P [I] [ 0 ] - T。
            他の 場合(P [I- 1 ] [ 1 ] == 2 
                ANS [i]は = MAX(ANS [I- 1 ]、P [I] [0 ] - T)。
             ANS [I] = MAX(P [I] [ 0 ] / 2 + P [I- 1 ] [ 0 ] / 2、P [I] [ 0 ] - T)。
        } 
    (I、N、につき1 であれば(P [I] [ 1 ] == 1 ){
             場合(I == N)は、
                ANS [I] = P [I] [ 0 ] + T。
            他の 場合(P [I + 1 ] [ 1 ] == 1 
                ANS [I]=分(ANS [I + 1 ]、P [I] [ 0 ] + T)。
             ANS [I] =分(P [I] [ 0 ] / 2 + P [I + 1 ] [ 0 ] / 2、P [I] [ 0 ] + T)。
        } 
    担当者は、(iは、1、Q)のprintf(" %Dの\ nは" 、[Q [I]をANS)。
    リターン 0 ; 
}
コードの表示

 

 

ただし、これはいない点が、この質問非正ソリューションの練習でもO(N logN個)は、一定の巨人小さな、正の解は、上記O(N)よりも高速に実行することです!

アイデア:各ミーティングポイントの前処理、及び位置又は+ -tは、それ以外のミーティングポイント、または出力する場合は、最も近いミーティングポイント、出力POS + tがPOS-Tに最も近い点が発生する可能性があるかどうかを確認します。バイナリ検索、もう少し詳しく説明し、特別な注意が必要です。

コード:

#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

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

おすすめ

転載: www.cnblogs.com/smilke/p/11533230.html