传送门:http://codeforces.com/contest/331/problem/D3
第一篇blog送给这道折磨我一上午的码农题。
题目大意很简单:b*b的平面上有n条互不相交且平行于坐标轴的有向线段,运动到线段上之后运动方向会改变成沿着线段的方向。
有q组询问,每组给出起始坐标,出发方向和运动距离,求最后停在哪个位置。如果中途会离开平面范围内就输出从哪个位置离开的。
一个自然的想法是:把询问离线,考虑计算从每条线段的终点以及每组询问的起点出发,下一次拐弯是在哪里。
我们可以将4个方向分开做,对于一个方向,我们把所有线段及询问按照这个方向排序(如方向为向右,则按照x坐标从大到小排序),用扫描线进行处理:扫到一条线段时,将它覆盖的区间插入线段树,计算答案时直接查询即可。
把这个拐弯关系建成图,由于一个点只会有1条出边,所以图会是个内向基环树森林,可以直接倍增预处理。
当然这个题细节很多:
怎么处理一条路径在某条线段的中间拐弯?我们可以在拐弯处插入一个新节点。
对于离开平面的情况,在离开平面处建一个点,并把它的出边指向自己。
还要注意一点:虽然保证线段不相交,但并不保证询问的起点不在线段上,因此这里要小心地特判。
4遍线段树+大量的细节特判让这个题很考验代码能力,我折腾了一上午,写代码1.5h+调试约1h,最后码长6.2k。
总结:一道不可多得的集思维难度代码难度为一体的好题。
(感谢可爱的kevinshuai小学妹Mys_C_K的安利)
#include<bits/stdc++.h>
using namespace std;
#define li long long
#define gc getchar()
#define pc putchar
li read(){
li x = 0,c = gc;
while(!isdigit(c)) c = gc;
while(isdigit(c)){
x = (x << 1) + (x << 3) + (c ^ '0');
c = gc;
}
return x;
}
void print(li q){
if(q >= 10) print(q / 10);
pc(q % 10 + '0');
}
int n,s,m;
struct jt{
int xa,ya,xb,yb,p,id;
int mxx,mxy,mnx,mny;
bool fg;
}a[500010],d[500010];
int asx[100010],asy[100010];
struct qy{
int x,y,p;
li t;
}b[100010];
int tot;
//D 0
//R 1
//U 2
//L 3
inline bool cp0(jt q,jt w){return q.mny == w.mny ? q.fg < w.fg : q.mny < w.mny;}
inline bool cp1(jt q,jt w){return q.mxx == w.mxx ? q.fg < w.fg : q.mxx > w.mxx;}
inline bool cp2(jt q,jt w){return q.mxy == w.mxy ? q.fg < w.fg : q.mxy > w.mxy;}
inline bool cp3(jt q,jt w){return q.mnx == w.mnx ? q.fg < w.fg : q.mnx < w.mnx;}
int t[500010];
#define ls q << 1
#define rs q << 1 | 1
#define ln ls,l,mid
#define rn rs,mid + 1,r
#define md int mid = l + r >> 1
void init(int q,int l,int r){
t[q] = -1;
if(l == r) return;
md;
init(ln);init(rn);
}
inline void ps(int q){
if(t[q] == -1) return;
t[ls] = t[rs] = t[q];t[q] = -1;
}
void xg(int q,int l,int r,int al,int ar,int x){
if(l >= al && r <= ar){
t[q] = x;
return;
}
ps(q);
md;
if(mid >= al) xg(ln,al,ar,x);
if(mid < ar) xg(rn,al,ar,x);
}
int cx(int q,int l,int r,int x){
if(l == r) return t[q];
ps(q);
md;
if(mid >= x) return cx(ln,x);
return cx(rn,x);
}
int s1[62][500010];
li s2[62][500010];
inline void ins(int u,int v,int w){s1[0][u] = v;s2[0][u] = w;}
inline void buildst(){
register int i,j;
for(i = 1;i <= 60;++i){
for(j = 1;j <= tot;++j){
s1[i][j] = s1[i - 1][s1[i - 1][j]];
s2[i][j] = s2[i - 1][j] + s2[i - 1][s1[i - 1][j]];
if(s2[i][j] > 1e18) s2[i][j] = 2e18;
}
}
}
void file(){
freopen("331d3.in","r",stdin);
freopen("331d3.out","w",stdout);
}
int main(){
//file();
int i,j,u;
char c;
n = read();s = read();
for(i = 1;i <= n;++i){
a[i].xa = read();a[i].ya = read();a[i].xb = read();a[i].yb = read();
if(a[i].xa == a[i].xb && a[i].ya == a[i].yb){
--n;--i;continue;
}
if(a[i].xa == a[i].xb){
if(a[i].ya < a[i].yb) a[i].p = 2;
else a[i].p = 0;
}
else{
if(a[i].xa < a[i].xb) a[i].p = 1;
else a[i].p = 3;
}
a[i].id = i;
}
m = read();tot = n + m;
for(i = 1;i <= m;++i){
b[i].x = read();b[i].y = read();c = gc;while(c < 'A' || c > 'Z') c = gc;b[i].t = read();
b[i].p = c == 'D' ? 0 : c == 'R' ? 1 : c == 'U'? 2 : 3;
a[i + n].xa = a[i + n].xb = b[i].x;a[i + n].ya = a[i + n].yb = b[i].y;a[i + n].id = i + n;a[i + n].p = b[i].p;a[i + n].fg = 1;
}
for(i = 1;i <= n + m;++i){
a[i].mxx = max(a[i].xa,a[i].xb);a[i].mnx = min(a[i].xa,a[i].xb);
a[i].mxy = max(a[i].ya,a[i].yb);a[i].mny = min(a[i].ya,a[i].yb);
}
#define x1 xa
#define y1 ya
#define x2 xb
#define y2 yb
//D 0
sort(a + 1,a + n + m + 1,cp0);
init(1,0,s);
for(i = 1;i <= n + m;++i){
if(!a[i].fg){
if(a[i].p != 0) xg(1,0,s,a[i].mnx,a[i].mxx,i);
}
if(a[i].p == 0){
u = cx(1,0,s,a[i].mxx);
a[++tot].x1 = a[i].mxx;a[tot].id = tot;
if(u == -1){
a[tot].y1 = 0;
ins(a[i].id,tot,a[i].mny);
ins(tot,tot,0);
}
else{
if(a[u].p == 2){
a[tot].y1 = min(a[i].mny,a[u].mxy);
ins(tot,a[u].id,a[u].mxy - a[tot].y1);
}
else{
a[tot].y1 = a[u].mxy;
ins(tot,a[u].id,abs(a[u].x2 - a[tot].x1));
}
ins(a[i].id,tot,a[i].mny - a[tot].y1);
}
}
}
//R 1
sort(a + 1,a + n + m + 1,cp1);
init(1,0,s);
for(i = 1;i <= n + m;++i){
if(!a[i].fg){
if(a[i].p != 1) xg(1,0,s,a[i].mny,a[i].mxy,i);
}
if(a[i].p == 1){
u = cx(1,0,s,a[i].mxy);
a[++tot].y1 = a[i].mxy;a[tot].id = tot;
if(u == -1){
a[tot].x1 = s;
ins(a[i].id,tot,s - a[i].mxx);
ins(tot,tot,0);
}
else{
if(a[u].p == 3){
a[tot].x1 = max(a[i].mxx,a[u].mnx);
ins(tot,a[u].id,a[tot].x1 - a[u].mnx);
}
else{
a[tot].x1 = a[u].mxx;
ins(tot,a[u].id,abs(a[u].y2 - a[tot].y1));
}
ins(a[i].id,tot,a[tot].x1 - a[i].mxx);
}
}
}
//U 2
sort(a + 1,a + n + m + 1,cp2);
init(1,0,s);
for(i = 1;i <= n + m;++i){
if(!a[i].fg){
if(a[i].p != 2) xg(1,0,s,a[i].mnx,a[i].mxx,i);
}
if(a[i].p == 2){
u = cx(1,0,s,a[i].mxx);
a[++tot].x1 = a[i].mxx;a[tot].id = tot;
if(u == -1){
a[tot].y1 = s;
ins(a[i].id,tot,s - a[i].mxy);
ins(tot,tot,0);
}
else{
if(a[u].p == 0){
a[tot].y1 = max(a[i].mxy,a[u].mny);
ins(tot,a[u].id,a[tot].y1 - a[u].mny);
}
else{
a[tot].y1 = a[u].mxy;
ins(tot,a[u].id,abs(a[u].x2 - a[tot].x1));
}
ins(a[i].id,tot,a[tot].y1 - a[i].mxy);
}
}
}
//L 3
sort(a + 1,a + n + m + 1,cp3);
init(1,0,s);
for(i = 1;i <= n + m;++i){
if(!a[i].fg){
if(a[i].p != 3) xg(1,0,s,a[i].mny,a[i].mxy,i);
}
if(a[i].p == 3){
u = cx(1,0,s,a[i].mxy);
a[++tot].y1 = a[i].mxy;a[tot].id = tot;
if(u == -1){
a[tot].x1 = 0;
ins(a[i].id,tot,a[i].mnx);
ins(tot,tot,0);
}
else{
if(a[u].p == 1){
a[tot].x1 = min(a[i].mnx,a[u].mxx);
ins(tot,a[u].id,a[u].mxx - a[tot].x1);
}
else{
a[tot].x1 = a[u].mxx;
ins(tot,a[u].id,abs(a[u].y2 - a[tot].y1));
}
ins(a[i].id,tot,a[i].mnx - a[tot].x1);
}
}
}
for(i = n + m + 1;i <= tot;++i) a[i].x2 = a[i].x1,a[i].y2 = a[i].y1;
for(i = 1;i <= tot;++i) d[a[i].id] = a[i];
buildst();
li nw,lft;
for(i = 1;i <= tot;++i) if(d[i].fg){
nw = i;lft = b[d[i].id - n].t;
for(j = 60;j >= 0;--j) if(lft >= s2[j][nw]){
lft -= s2[j][nw];
nw = s1[j][nw];
}
asx[d[i].id - n] = d[nw].x2;asy[d[i].id - n] = d[nw].y2;
if(s1[0][nw] != nw){
if(d[s1[0][nw]].x2 > d[nw].x2) asx[d[i].id - n] += lft;
else if(d[s1[0][nw]].x2 < d[nw].x2) asx[d[i].id - n] -= lft;
else if(d[s1[0][nw]].y2 > d[nw].y2) asy[d[i].id - n] += lft;
else if(d[s1[0][nw]].y2 < d[nw].y2) asy[d[i].id - n] -= lft;
}
}
for(i = 1;i <= m;++i) print(asx[i]),pc(' '),print(asy[i]),pc('\n');
return 0;
}