1. 程式人生 > >Codeforces 331D3-線段樹+掃描線+倍增

Codeforces 331D3-線段樹+掃描線+倍增

傳送門

題意:

在n*n的座標內給出一些箭頭,給出一些出發點、出發方向以及出發時間,遇到箭頭就需要改變方向為箭頭的方向,對每個出發點求最後能走到哪

資料範圍1e5

Solution:

口胡起來特別簡單:對於不同方向的箭頭和出發點分別用線段樹+掃描線建出相應的圖,最後在建出的圖上跑倍增就可以了
我們可以把出發點看做沒有長度的箭頭,就可以和箭頭一起搞了,在建圖時我們可以新增一箇中間點作為一個箭頭延長後與另一個箭頭的交點,注意雖然題目上說箭頭不能重合,交叉,但是如果我們把出發點看成箭頭的話會出現箭頭包含箭頭的情況,這裡和走到邊界時都需要特殊處理一下
另外,由於倍增時可能會爆longlong,注意到時間是小於1e18的,所以我們倍增時如果發現倍增後的值大於1e18,就可以把這個值強制賦值為大於1e18的數

寫起來簡直要命。。。。。。

相當及其超級練習程式碼能力pwp

程式碼:

#include<cstdio>
#include<iostream>
#include<algorithm>
#define RR 1
#define LL 2
#define DD 3
#define UU 4 
#define debug(x) cerr<<#x<<"="<<x<<" "
using namespace std;
const int N=200010;
int n,b,x,y,tot,q;
int val[2*N],to[2
*N]; int st[2*N],tp; char s[2]; int go[2*N][70]; long long dis[2*N][70]; int vis[2*N]; int aabs(int a){return a<0?-a:a;} struct arrow{ int x1,y1,x2,y2,id,tag,dir; int maxx,minx,maxy,miny; void get() { maxx=max(x1,x2); minx=min(x1,x2); maxy=max(y1,y2); miny=min(y1,y2);
} }a[2*N],A[2*N];//1R 2L 3D 4U long long t[N]; struct tree{ int l,r,tag,v; }tr[4*N]; int ansx[N],ansy[N]; int dx[5]={0,1,-1,0,0}; int dy[5]={0,0,0,-1,1}; void build(int i,int l,int r) { tr[i].tag=-1;tr[i].l=l,tr[i].r=r;tr[i].v=-1; if (l==r) return; int mid=l+r>>1; build(i<<1,l,mid);build(i<<1|1,mid+1,r); } void pushdown(int i) { if (tr[i].tag!=-1) { if (tr[i].l==tr[i].r) tr[i].v=tr[i].tag; else tr[i<<1].tag=tr[i].tag,tr[i<<1|1].tag=tr[i].tag; tr[i].tag=-1; } } void modify(int i,int l,int r,int v) { int L=tr[i].l,R=tr[i].r; if (l>R||L>r) return; pushdown(i); if (l<=L&&R<=r) {if (L==R) tr[i].v=v;else tr[i].tag=v;return;} modify(i<<1,l,r,v);modify(i<<1|1,l,r,v); } int query(int i,int pos) { int L=tr[i].l,R=tr[i].r; pushdown(i); if (L==R) return tr[i].v; int mid=L+R>>1; if (mid>=pos) return query(i<<1,pos);else return query(i<<1|1,pos); } void addedg(int x,int y,int v){to[x]=y,val[x]=v;} bool cmp1(arrow a,arrow b){return (a.maxx==b.maxx)?a.tag<b.tag:a.maxx>b.maxx;} bool cmp2(arrow a,arrow b){return (a.minx==b.minx)?a.tag<b.tag:a.minx<b.minx;} bool cmp4(arrow a,arrow b){return (a.maxy==b.maxy)?a.tag<b.tag:a.maxy>b.maxy;} bool cmp3(arrow a,arrow b){return (a.miny==b.miny)?a.tag<b.tag:a.miny<b.miny;} int main() { scanf("%d%d",&n,&b); for (int i=1;i<=n;i++) { scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2); a[i].tag=0;a[i].id=i; if (a[i].x2==a[i].x1&&a[i].y1==a[i].y2) {n--,i--;continue;} if (a[i].x1<a[i].x2) a[i].dir=1; else if (a[i].x1>a[i].x2) a[i].dir=2; else if (a[i].y1<a[i].y2) a[i].dir=4; else if (a[i].y1>a[i].y2) a[i].dir=3; } scanf("%d",&q); for (int i=1;i<=q;i++) { scanf("%d%d%s%I64d",&x,&y,s,&t[i]); a[i+n].x1=x,a[i+n].x2=x; a[i+n].y1=y,a[i+n].y2=y; a[i+n].tag=1;a[i+n].id=i+n; if (s[0]=='R') a[i+n].dir=1; else if (s[0]=='L') a[i+n].dir=2; else if (s[0]=='D') a[i+n].dir=3; else a[i+n].dir=4; } tot=n+q; for (int i=1;i<=n+q;i++) a[i].get(); //R sort(a+1,a+1+n+q,cmp1); build(1,0,b); for (int i=1;i<=n+q;i++) { if (a[i].tag==0) { if (a[i].dir==LL) modify(1,a[i].y1,a[i].y2,i); else if (a[i].dir==UU) modify(1,a[i].y1,a[i].y2,i); else if (a[i].dir==DD) modify(1,a[i].y2,a[i].y1,i); } if (a[i].dir==RR) { int nw=query(1,a[i].y1); tot++; a[tot].id=tot; a[tot].y1=a[i].y1; if (nw!=-1) { if (a[nw].dir==LL) addedg(tot,a[nw].id,max(0,a[i].x2-a[nw].x2)),a[tot].x1=max(a[i].x2,a[nw].x2); else addedg(tot,a[nw].id,aabs(a[nw].y2-a[i].y2)),a[tot].x1=a[nw].x1; addedg(a[i].id,tot,max(0,a[nw].x2-a[i].x2)); } else { a[tot].x1=b; addedg(a[i].id,tot,b-a[i].x2); addedg(tot,tot,1); } } } //L sort(a+1,a+1+n+q,cmp2); build(1,0,b); for (int i=1;i<=n+q;i++) { if (a[i].tag==0) { if (a[i].dir==RR) modify(1,a[i].y1,a[i].y2,i); else if (a[i].dir==UU) modify(1,a[i].y1,a[i].y2,i); else if (a[i].dir==DD) modify(1,a[i].y2,a[i].y1,i); } if (a[i].dir==LL) { int nw=query(1,a[i].y1); tot++; a[tot].id=tot; a[tot].y1=a[i].y1; if (nw!=-1) { if (a[nw].dir==RR) addedg(tot,a[nw].id,max(0,a[nw].x2-a[i].x2)),a[tot].x1=min(a[i].x2,a[nw].x2); else addedg(tot,a[nw].id,aabs(a[nw].y2-a[i].y2)),a[tot].x1=a[nw].x1; addedg(a[i].id,tot,max(0,a[i].x2-a[nw].x2)); } else { a[tot].x1=0; addedg(a[i].id,tot,a[i].x2); addedg(tot,tot,1); } } } //D sort(a+1,a+1+n+q,cmp3); build(1,0,b); for (int i=1;i<=n+q;i++) { if (a[i].tag==0) { if (a[i].dir==LL) modify(1,a[i].x2,a[i].x1,i); else if (a[i].dir==UU) modify(1,a[i].x1,a[i].x2,i); else if (a[i].dir==RR) modify(1,a[i].x1,a[i].x2,i); } if (a[i].dir==DD) { int nw=query(1,a[i].x1); tot++; a[tot].id=tot; a[tot].x1=a[i].x1; if (nw!=-1) { if (a[nw].dir==UU) addedg(tot,a[nw].id,max(0,a[nw].y2-a[i].y2)),a[tot].y1=min(a[i].y2,a[nw].y2); else addedg(tot,a[nw].id,aabs(a[nw].x2-a[i].x2)),a[tot].y1=a[nw].y1; addedg(a[i].id,tot,max(0,a[i].y2-a[nw].y2)); } else { a[tot].y1=0; addedg(a[i].id,tot,a[i].y2); addedg(tot,tot,1); } } } //U sort(a+1,a+1+n+q,cmp4); build(1,0,b); for (int i=1;i<=n+q;i++) { if (a[i].tag==0) { if (a[i].dir==LL) modify(1,a[i].x2,a[i].x1,i); else if (a[i].dir==DD) modify(1,a[i].x1,a[i].x2,i); else if (a[i].dir==RR) modify(1,a[i].x1,a[i].x2,i); } if (a[i].dir==UU) { int nw=query(1,a[i].x1); tot++; a[tot].id=tot; a[tot].x1=a[i].x1; if (nw!=-1) { if (a[nw].dir==DD) addedg(tot,a[nw].id,max(0,a[i].y2-a[nw].y2)),a[tot].y1=max(a[i].y2,a[nw].y2); else addedg(tot,a[nw].id,aabs(a[nw].x2-a[i].x2)),a[tot].y1=a[nw].y1; addedg(a[i].id,tot,max(0,a[nw].y2-a[i].y2)); } else { a[tot].y1=b; addedg(a[i].id,tot,b-a[i].y2); addedg(tot,tot,1); } } } for (int i=n+q+1;i<=tot;i++) a[i].x2=a[i].x1,a[i].y2=a[i].y1; for (int i=1;i<=tot;i++) A[a[i].id]=a[i]; for (int i=1;i<=tot;i++) dis[i][0]=val[i],go[i][0]=to[i]; for (int i=1;i<=60;i++) for (int j=1;j<=tot;j++) { go[j][i]=go[go[j][i-1]][i-1]; dis[j][i]=dis[j][i-1]+dis[go[j][i-1]][i-1]; if (dis[j][i]>1e18) dis[j][i]=2e18; } for (int i=1;i<=tot;i++) { if (a[i].tag==1) { int pos=a[i].id; long long nw=t[a[i].id-n]; for (int i=60;i>=0;i--) { if (nw-dis[pos][i]>=0) nw-=dis[pos][i],pos=go[pos][i]; } int d=0; if (A[pos].x1<A[to[pos]].x2) d=1; else if (A[pos].x1>A[to[pos]].x2) d=2; else if (A[pos].y1<A[to[pos]].y2) d=4; else if (A[pos].y1>A[to[pos]].y2) d=3; ansx[a[i].id-n]=A[pos].x2+dx[d]*nw; ansy[a[i].id-n]=A[pos].y2+dy[d]*nw; } } for (int i=1;i<=q;i++) printf("%d %d\n",ansx[i],ansy[i]); }