[소 오프 네트워크] 창고지기 이산 세그먼트 트리 간격 따르면]

판사 온라인 : 훈련 캠프 전에 가축 오프 네트워크 NOIP2018 - 그룹을 개선 (세션 8) T2

레이블 : 이산, 트리 라인 간격 범위

추신 :이 제목은 다음과 같은 항목이 적응을 설명하므로 피사체가 여전히 동일 인해 오프라인 시뮬레이션 게임으로 변경되었습니다.


제목 설명

마지막으로, 스웨덴 (으)로 운항하는 셀던 오늘은 노벨상을 가져왔다. 쉘든, 레너드, 페니, 하워드, 베르나 데트의 좋은 친구로서, 인 Rajesh 갈 것입니다. 그러나, 너무 많은 수하물, 모두 1 층 조용히 엘리베이터를 기다리고에 계단을 걸어, 엘리베이터에 쌓여 짐에 있었다.

불행하게도, 짐이 쌓여 너무 높은, 엘리베이터 문이 바닥에 흩어져 가방에 열었습니다. 바닥면은 트렁크 대략 직사각형으로서 것처럼 공교롭게도, 각각의 타일의 수직 에지를 각각 오른쪽으로 x 축 양의 방향을 좌표축으로 정의되고, 각각의 측면은 각각의 트렁크 평행 축과 중복되지 않습니다.

셀던에 의해 선택하면 셀던 그것은 레너드에 문제를 제기 장면을이 시간을보고, 레너드에 의해 가방은 초 단위 당 1의 비율로 바로 이동에있는 상자를 밀었다. 프런트 간선 도로에 실행하는 경우, 회전 또는 움직임의 방향을 변경하지 않습니다, 오른쪽으로 한 단위의 속도로, 만남의 순간에 운동으로 시작됩니다 트렁크에 명중되었다. 고려 레너드는 심한 천식 환자, 그래서 그는 단지를 주장 할 수 K 중지하는 데 필요한 초. 중지하고 모든화물의 위치가 될 때 레너드와 쉘던은 알고 싶어.

구체적으로는, 이동 상태 난 경우에만, 한 번에 한 상자 : i는 선택 박스 또는 I 및 Y에있는 박스의 우측 경계의 좌측 경계까지 동일한 이동 상태 J의 박스가 존재 공통 축 길이> 0 예상. 각 사각형의 어느 순간에 여전히 교차하지 않는,이 경우에 그것을 찾을 수 있습니다.

(결국, 십년의 룸메이트가), 다음 이전 X이 질문에 대답 할 수 레너드는 문제가 너무 바보라고 생각하지만 거절 죄송합니다. 기존 X가 성공적으로 질문 셀던를 응답 한 경우, 레너드는 쉘든은 스웨덴 된 X를 함께 가져올 것이다 만들 것입니다.

기입

두 정수 N, t 및 K의 첫 번째 줄. 셀던은 t 번째 수하물의 입력을 선택하기 시작했다. 다음 4 개 라인마다, n은 수화물의 정수 왼쪽 아래 구석 좌표를 나타낸다 (\ (x1_i, y1_i)를 \) , 오른쪽 위 좌표 (\ (x2_i, y2_i)는 \) .

수출

출력 라인 N의 정수, X는 정수를 나타내고, I 번째 내가 초 짐 번째 (k)의 왼쪽 아래 모서리의 좌표.

당신은이 값이 고유 트렁크의 위치를 ​​확인할 수 있습니다 알고 찾을 수 있습니다.

견본

입력

5 1 1
1 1 2 3
2 2 3 5
3 4 4 5
4 2 5 5
5 1 6 3

산출

2 3 4 5 6

힌트

데이터의 30 %에 대해서는 \ (k≤100 \) .

데이터의 다른 40 %를 들어 \ (n≤1000 \) .

데이터의 100 %, \ (^ 5,1≤t≤n N, 10 ≤ 9 1≤k≤10는 ^ \) , 모든 좌표는 (\ - 10 ^ 9 \)\ (10 ^ 9 \) 사이.

데이터 수하물은 두 개의 분리 된을 보장합니다.

문제 해결

첫 번째는 기반으로 (X1의 \) \ 모든 상자를 정렬합니다. 우리는 각 상자 알고 처음으로이 시간 밀려 \ (\ TI) 각 상자의 마지막의 위치를 계산합니다.

오프 마찰 방지하기 위해, 우리가 처음 시작 \을 (Y2 - \) . 따라서 한 개의 지점 종축 존재 구성하는 두 부분 교차 충돌 나타낸다. 가정하면 (I는 \) \ 앞에 충돌되고, \는 (I는 \) 칠 수 \ (J \) 다음 \ (TI [J] = 분 (TI [J], TI [I] + X1 [J] -X2 [I]) \) .

데이터의 70 %, 직접 폭력 들어 \ (O (N) \) 최소값의 수하물의 전면에 걸쳐 스위핑, 전체 시간 복잡도는 \ (O (N ^ 2) \) .

최소 걸릴 얼마나 빨리 고려, 사용할 수 분명 트리 라인을 최적화 할 수 있습니다. 첫 번째 좌표 이산은 다음 트리 라인의 일부 섹션에 값을 할당,이 간격은 이산 좌표입니다. 쿼리가 최소 수직 따른 쿼리 간격 인 경우에는 현재 위치의 좌표. 존재하는 어떤 값을 수식이었다 상기 관측 것을만큼 입금 \ (TI [I] -X2 [ 내가] \) 일 수있다. 트리 라인이 지원하는 범위의 범위를 최소 간격 쿼리 할 수 있습니다.

이 질문은 이상하지만, 실현주의해야 할 많은 세부 사항이 있습니다 :

1. 마지막으로 문장한다 (TI는 [] <= K는 \) \ , 소정 시간에 충돌을 보장한다.

세그먼트 트리 지정 구간의 지연 지연 태그의 시작이므로 2. 최대치 INF w를 최소 값이 할당되어야한다.

3. 개별 어레이 열려면 \ (2N \)를 각 상자에 대해 분산되어 있기 때문에, \ (Y1, Y2의 \) 전체 \ (2N \) 참조. 따라서, 트리 라인 어레이 크기 열려 \ (8N \) .

4. 시작 \ (Y2는 - \) , 상황이 스쳐 나타나지 않는지 확인합니다.

5. 때 시험 매우 어리석은 의심 : 한 두 개의 상자 충돌, 경우 상자 2 배의 앞> 사실, 아직 충돌하지 않는 상자 뒤에 1 개, 그림의 교차가, 종축, 보도 X1의 종류를 확인하는 방법 지도는이 동시에 qwq을 만족하지 수 있다는 것을 알고 있습니다.

다음과 같이 코드입니다 :

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,INF=1e9+2;
inline int read(){
    int x=0,e=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')e=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*e;
}
struct node{
    int x,y,x2,y2,id;
}o[N];
inline bool cmp(node a,node b){return a.x<b.x;}
int n,s,k,LIM;

struct sgt{
    int l,r,w,lazy;
}b[8*N];
void build(int o,int l,int r){
    b[o].l=l,b[o].r=r,b[o].w=INF,b[o].lazy=INF;
    if(l==r)return;
    int mid=l+r>>1;
    build(o<<1,l,mid);build(o<<1|1,mid+1,r);
}
void down(int o){
    if(b[o].lazy==INF)return ;
    int p=b[o].lazy;
    b[o<<1].w=min(b[o<<1].w,p);b[o<<1|1].w=min(b[o<<1|1].w,p);
    b[o<<1].lazy=min(b[o<<1].lazy,p);b[o<<1|1].lazy=min(b[o<<1|1].lazy,p);
    b[o].lazy=INF;
}
void update(int o,int l,int r,int d){
    if(b[o].l==l&&b[o].r==r){
        b[o].w=min(b[o].w,d);
        b[o].lazy=min(b[o].lazy,d);
        return;
    }
    down(o);
    int mid=b[o].l+b[o].r>>1;
    if(r<=mid)update(o<<1,l,r,d);
    else if(l>mid)update(o<<1|1,l,r,d);
    else{
        update(o<<1,l,mid,d);update(o<<1|1,mid+1,r,d);
    }
    b[o].w=min(b[o<<1].w,b[o<<1|1].w);
}
int query(int o,int l,int r){
    if(b[o].l==l&&b[o].r==r)return b[o].w;
    down(o);
    int mid=b[o].l+b[o].r>>1;
    if(r<=mid)return query(o<<1,l,r);
    else if(l>mid)return query(o<<1|1,l,r);
    return min(query(o<<1,l,mid),query(o<<1|1,mid+1,r));
}
int ti[N],res[N];
int yy[2*N];
int main(){
    n=read(),s=read(),k=read();
    int tmp=0;
    for(register int i=1;i<=n;i++){
        int a=read(),b=read(),c=read(),d=read();
        d--;    
        o[i]=(node){a,b,c,d,i};
        yy[++tmp]=b,yy[++tmp]=d;
    }
    sort(o+1,o+n+1,cmp);
    sort(yy+1,yy+tmp+1);
    LIM=unique(yy+1,yy+tmp+1)-yy-1;
    
    for(register int i=1;i<=n;i++){
        o[i].y=lower_bound(yy+1,yy+LIM+1,o[i].y)-yy;
        o[i].y2=lower_bound(yy+1,yy+LIM+1,o[i].y2)-yy;
    }
    build(1,1,LIM);
    int st;
    for(register int i=1;i<=n;i++)if(o[i].id==s){st=i;break;}
    ti[st]=1;
    update(1,o[st].y,o[st].y2,1-o[st].x2);
    for(register int i=st+1;i<=n;i++){
        int now=query(1,o[i].y,o[i].y2);    
        if(now==INF)continue;
        ti[i]=o[i].x+now;
        update(1,o[i].y,o[i].y2,ti[i]-o[i].x2);
    }
    for(register int i=1;i<=n;i++){
        if(ti[i]&&ti[i]<=k)res[o[i].id]=k-ti[i]+1+o[i].x;
        else res[o[i].id]=o[i].x;
    }
    for(register int i=1;i<n;i++)printf("%d ",res[i]);
    printf("%d\n",res[n]);
} 

추천

출처www.cnblogs.com/Tieechal/p/11488032.html