Codeforces 331D

题意

\(b*b\) 的平面上有 \(n\) 条有向线段,它们长度 \(≥1\) ,与坐标轴平行,且任意两条互不相交。现在有 \(m\) 个询问,每个询问表示从 \((x,y)\) 开始,初始方向为 \(dir\) ,走 \(t\) 步到达的位置。如果超出平面范围则输出从哪个位置超出的。\((n,m,b\le 10^5)\)

Examples

Input
3 3
0 0 0 1
0 2 2 2
3 3 2 3
12
0 0 L 0
0 0 L 1
0 0 L 2
0 0 L 3
0 0 L 4
0 0 L 5
0 0 L 6
2 0 U 2
2 0 U 3
3 0 U 5
1 3 D 2
1 3 R 2
Output
0 0
0 1
0 2
1 2
2 2
3 2
3 2
2 2
3 2
1 3
2 2
1 3

首先以每条线段为节点建一张图,用线段树扫描线维护。
然后我们发现这是一棵基环内向树(每个节点只有一条出边)。
于是对于每个节点搞倍增,询问时倍增即可。
但是询问要离线,原因是你得在搞线段树的同时把每个询问从图的哪个节点开始先弄出来。

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long D;
const int maxn=100003,maxlog=53;
const D INFll=4000000000000000000ll;
struct edge{int to,next,w;}e[maxn<<1];
int head[maxn],cnte;
void add(int u,int v,int w){e[++cnte].to=v,e[cnte].w=w,e[cnte].next=head[u],head[u]=cnte;}
struct node{int num,z;}t[maxn<<2];
void pushdown(int p,int l,int r){
    if(l==r)return;
    if(t[p].z){
        t[p<<1].num=t[p<<1|1].num=t[p<<1].z=t[p<<1|1].z=t[p].z;
        t[p].z=0;
    }
}
void build(int p,int l,int r){
    t[p].num=t[p].z=0;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
}
void change(int p,int l,int r,int seg_l,int seg_r,int k){
    pushdown(p,l,r);
    if(seg_l<=l&&r<=seg_r){
        t[p].num=t[p].z=k;
        return;
    }
    int mid=(l+r)>>1;
    if(seg_l<=mid)change(p<<1,l,mid,seg_l,seg_r,k);
    if(seg_r>mid)change(p<<1|1,mid+1,r,seg_l,seg_r,k);
}
int query(int p,int l,int r,int pos){
    pushdown(p,l,r);
    if(l==r)return t[p].num;
    int mid=(l+r)>>1;
    if(pos<=mid)return query(p<<1,l,mid,pos);
    else return query(p<<1|1,mid+1,r,pos);
}
struct segment{int x1,y1,x2,y2,num;}a[maxn];
struct QQ{int x,y,aim,num,dir;D t;}b[maxn];
int n,m,k,fa[maxn][maxlog],ans[maxn][2];
D cost[maxn][maxlog];
char mo[2];
int DIR(segment p){return p.x1==p.x2?(p.y1<p.y2?1:3):(p.x1<p.x2?0:2);}
int dist(int x1,int y1,int x2,int y2){return abs(x1-x2)+abs(y1-y2);}
int DIST(int x,int y,segment p){
    if(x>=min(p.x1,p.x2)&&x<=max(p.x1,p.x2)&&y>=min(p.y1,p.y2)&&y<=max(p.y1,p.y2))return 0;
    return x>=min(p.x1,p.x2)&&x<=max(p.x1,p.x2)?min(abs(y-p.y1),abs(y-p.y2)):min(abs(x-p.x1),abs(x-p.x2));
}
pair<int,int> MAP(int x,int y,segment p){
    if(x>=min(p.x1,p.x2)&&x<=max(p.x1,p.x2)&&y>=min(p.y1,p.y2)&&y<=max(p.y1,p.y2))return make_pair(x,y);
    return x>=min(p.x1,p.x2)&&x<=max(p.x1,p.x2)?
        make_pair(x,abs(y-p.y1)<abs(y-p.y2)?p.y1:p.y2):
        make_pair(abs(x-p.x1)<abs(x-p.x2)?p.x1:p.x2,y);
}
void initgraph(){
    build(1,0,k);
    sort(a+1,a+n+1,[](segment p,segment q){return min(p.y1,p.y2)<min(q.y1,q.y2);});
    sort(b+1,b+m+1,[](QQ p,QQ q){return p.y<q.y;});
    int j=1;
    for(int i=1;i<=n;i++){
        for(;j<=m&&b[j].y<min(a[i].y1,a[i].y2);j++)if(b[j].dir==3)b[j].aim=a[query(1,0,k,b[j].x)].num;
        if(a[i].x1==a[i].x2&&a[i].y1>a[i].y2){
            int v=query(1,0,k,a[i].x1);
            if(v)add(a[i].num,a[v].num,dist(a[i].x2,a[i].y2,a[v].x2,a[v].y2));
        }
        else{
            change(1,0,k,min(a[i].x1,a[i].x2),max(a[i].x1,a[i].x2),i);
        }
    }
    for(;j<=m;j++)if(b[j].dir==3)b[j].aim=a[query(1,0,k,b[j].x)].num;

    build(1,0,k);
    sort(a+1,a+n+1,[](segment p,segment q){return max(p.y1,p.y2)>max(q.y1,q.y2);});
    sort(b+1,b+m+1,[](QQ p,QQ q){return p.y>q.y;});
    j=1;
    for(int i=1;i<=n;i++){
        for(;j<=m&&b[j].y>max(a[i].y1,a[i].y2);j++)if(b[j].dir==1)b[j].aim=a[query(1,0,k,b[j].x)].num;
        if(a[i].x1==a[i].x2&&a[i].y1<a[i].y2){
            int v=query(1,0,k,a[i].x1);
            if(v)add(a[i].num,a[v].num,dist(a[i].x2,a[i].y2,a[v].x2,a[v].y2));
        }
        else{
            change(1,0,k,min(a[i].x1,a[i].x2),max(a[i].x1,a[i].x2),i);
        }
    }
    for(;j<=m;j++)if(b[j].dir==1)b[j].aim=a[query(1,0,k,b[j].x)].num;

    build(1,0,k);
    sort(a+1,a+n+1,[](segment p,segment q){return max(p.x1,p.x2)>max(q.x1,q.x2);});
    sort(b+1,b+m+1,[](QQ p,QQ q){return p.x>q.x;});
    j=1;
    for(int i=1;i<=n;i++){
        for(;j<=m&&b[j].x>max(a[i].x1,a[i].x2);j++)if(b[j].dir==0)b[j].aim=a[query(1,0,k,b[j].y)].num;
        if(a[i].y1==a[i].y2&&a[i].x1<a[i].x2){
            int v=query(1,0,k,a[i].y1);
            if(v)add(a[i].num,a[v].num,dist(a[i].x2,a[i].y2,a[v].x2,a[v].y2));
        }
        else{
            change(1,0,k,min(a[i].y1,a[i].y2),max(a[i].y1,a[i].y2),i);
        }
    }
    for(;j<=m;j++)if(b[j].dir==0)b[j].aim=a[query(1,0,k,b[j].y)].num;

    build(1,0,k);
    sort(a+1,a+n+1,[](segment p,segment q){return min(p.x1,p.x2)<min(q.x1,q.x2);});
    sort(b+1,b+m+1,[](QQ p,QQ q){return p.x<q.x;});
    j=1;
    for(int i=1;i<=n;i++){
        for(;j<=m&&b[j].x<min(a[i].x1,a[i].x2);j++)if(b[j].dir==2)b[j].aim=a[query(1,0,k,b[j].y)].num;
        if(a[i].y1==a[i].y2&&a[i].x1>a[i].x2){
            int v=query(1,0,k,a[i].y1);
            if(v)add(a[i].num,a[v].num,dist(a[i].x2,a[i].y2,a[v].x2,a[v].y2));
        }
        else{
            change(1,0,k,min(a[i].y1,a[i].y2),max(a[i].y1,a[i].y2),i);
        }
    }
    for(;j<=m;j++)if(b[j].dir==2)b[j].aim=a[query(1,0,k,b[j].y)].num;
}
int main(){
    scanf("%d%d",&n,&k);
    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].num=i;
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d%s%lld",&b[i].x,&b[i].y,mo,&b[i].t);
        b[i].num=i,b[i].dir=(*mo=='R'?0:(*mo=='U'?1:(*mo=='L'?2:3)));
    }
    initgraph();
    sort(a+1,a+n+1,[](segment p,segment q){return p.num<q.num;});
    for(int i=1;i<=n;i++){
        if(head[i])fa[i][0]=e[head[i]].to,cost[i][0]=e[head[i]].w;
        else cost[i][0]=INFll;
    }
    for(int j=1;j<=50;j++){
        for(int i=1;i<=n;i++){
            fa[i][j]=fa[fa[i][j-1]][j-1];
            cost[i][j]=cost[i][j-1]+cost[fa[i][j-1]][j-1];
            if(cost[i][j]>INFll)cost[i][j]=INFll;
        }
    }
    for(int i=1;i<=m;i++){
        int s=b[i].aim,&X=ans[b[i].num][0],&Y=ans[b[i].num][1];
        if(s){
            if(b[i].t>dist(b[i].x,b[i].y,a[s].x2,a[s].y2)){
                b[i].t-=dist(b[i].x,b[i].y,a[s].x2,a[s].y2);
                for(int j=50;j>=0&&b[i].t>0;j--){
                    if(b[i].t>=cost[s][j])b[i].t-=cost[s][j],s=fa[s][j];
                }
                b[i].x=a[s].x2,b[i].y=a[s].y2,b[i].dir=DIR(a[s]),s=fa[s][0];
            }
            if(s&&b[i].t>DIST(b[i].x,b[i].y,a[s])){
                pair<int,int> mp=MAP(b[i].x,b[i].y,a[s]);
                b[i].t-=DIST(b[i].x,b[i].y,a[s]),b[i].x=mp.first,b[i].y=mp.second,b[i].dir=DIR(a[s]);
            }
        }
        switch(b[i].dir){
            case 0:X=min(b[i].x+b[i].t,D(k)),Y=b[i].y;break;
            case 1:X=b[i].x,Y=min(b[i].y+b[i].t,D(k));break;
            case 2:X=max(b[i].x-b[i].t,0ll),Y=b[i].y;break;
            case 3:X=b[i].x,Y=max(b[i].y-b[i].t,0ll);break;
        }
    }
    for(int i=1;i<=m;i++)printf("%d %d\n",ans[i][0],ans[i][1]);
    return 0;
}

格式化:

#include <bits/stdc++.h>
using namespace std;
typedef long long D;
const int maxn = 100003, maxlog = 53;
const D INFll = 4000000000000000000ll;
struct edge
{
    int to, next, w;
} e[maxn << 1];
int head[maxn], cnte;
void add(int u, int v, int w) { e[++cnte].to = v, e[cnte].w = w, e[cnte].next = head[u], head[u] = cnte; }
struct node
{
    int num, z;
} t[maxn << 2];
void pushdown(int p, int l, int r)
{
    if (l == r)
        return;
    if (t[p].z)
    {
        t[p << 1].num = t[p << 1 | 1].num = t[p << 1].z = t[p << 1 | 1].z = t[p].z;
        t[p].z = 0;
    }
}
void build(int p, int l, int r)
{
    t[p].num = t[p].z = 0;
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
}
void change(int p, int l, int r, int seg_l, int seg_r, int k)
{
    pushdown(p, l, r);
    if (seg_l <= l && r <= seg_r)
    {
        t[p].num = t[p].z = k;
        return;
    }
    int mid = (l + r) >> 1;
    if (seg_l <= mid)
        change(p << 1, l, mid, seg_l, seg_r, k);
    if (seg_r > mid)
        change(p << 1 | 1, mid + 1, r, seg_l, seg_r, k);
}
int query(int p, int l, int r, int pos)
{
    pushdown(p, l, r);
    if (l == r)
        return t[p].num;
    int mid = (l + r) >> 1;
    if (pos <= mid)
        return query(p << 1, l, mid, pos);
    else
        return query(p << 1 | 1, mid + 1, r, pos);
}
struct segment
{
    int x1, y1, x2, y2, num;
} a[maxn];
struct QQ
{
    int x, y, aim, num, dir;
    D t;
} b[maxn];
int n, m, k, fa[maxn][maxlog], ans[maxn][2];
D cost[maxn][maxlog];
char mo[2];
int DIR(segment p) { return p.x1 == p.x2 ? (p.y1 < p.y2 ? 1 : 3) : (p.x1 < p.x2 ? 0 : 2); }
int dist(int x1, int y1, int x2, int y2) { return abs(x1 - x2) + abs(y1 - y2); }
int DIST(int x, int y, segment p)
{
    if (x >= min(p.x1, p.x2) && x <= max(p.x1, p.x2) && y >= min(p.y1, p.y2) && y <= max(p.y1, p.y2))
        return 0;
    return x >= min(p.x1, p.x2) && x <= max(p.x1, p.x2) ? min(abs(y - p.y1), abs(y - p.y2)) : min(abs(x - p.x1), abs(x - p.x2));
}
pair<int, int> MAP(int x, int y, segment p)
{
    if (x >= min(p.x1, p.x2) && x <= max(p.x1, p.x2) && y >= min(p.y1, p.y2) && y <= max(p.y1, p.y2))
        return make_pair(x, y);
    return x >= min(p.x1, p.x2) && x <= max(p.x1, p.x2) ? make_pair(x, abs(y - p.y1) < abs(y - p.y2) ? p.y1 : p.y2) : make_pair(abs(x - p.x1) < abs(x - p.x2) ? p.x1 : p.x2, y);
}
void initgraph()
{
    build(1, 0, k);
    sort(a + 1, a + n + 1, [](segment p, segment q) { return min(p.y1, p.y2) < min(q.y1, q.y2); });
    sort(b + 1, b + m + 1, [](QQ p, QQ q) { return p.y < q.y; });
    int j = 1;
    for (int i = 1; i <= n; i++)
    {
        for (; j <= m && b[j].y < min(a[i].y1, a[i].y2); j++)
            if (b[j].dir == 3)
                b[j].aim = a[query(1, 0, k, b[j].x)].num;
        if (a[i].x1 == a[i].x2 && a[i].y1 > a[i].y2)
        {
            int v = query(1, 0, k, a[i].x1);
            if (v)
                add(a[i].num, a[v].num, dist(a[i].x2, a[i].y2, a[v].x2, a[v].y2));
        }
        else
        {
            change(1, 0, k, min(a[i].x1, a[i].x2), max(a[i].x1, a[i].x2), i);
        }
    }
    for (; j <= m; j++)
        if (b[j].dir == 3)
            b[j].aim = a[query(1, 0, k, b[j].x)].num;

    build(1, 0, k);
    sort(a + 1, a + n + 1, [](segment p, segment q) { return max(p.y1, p.y2) > max(q.y1, q.y2); });
    sort(b + 1, b + m + 1, [](QQ p, QQ q) { return p.y > q.y; });
    j = 1;
    for (int i = 1; i <= n; i++)
    {
        for (; j <= m && b[j].y > max(a[i].y1, a[i].y2); j++)
            if (b[j].dir == 1)
                b[j].aim = a[query(1, 0, k, b[j].x)].num;
        if (a[i].x1 == a[i].x2 && a[i].y1 < a[i].y2)
        {
            int v = query(1, 0, k, a[i].x1);
            if (v)
                add(a[i].num, a[v].num, dist(a[i].x2, a[i].y2, a[v].x2, a[v].y2));
        }
        else
        {
            change(1, 0, k, min(a[i].x1, a[i].x2), max(a[i].x1, a[i].x2), i);
        }
    }
    for (; j <= m; j++)
        if (b[j].dir == 1)
            b[j].aim = a[query(1, 0, k, b[j].x)].num;

    build(1, 0, k);
    sort(a + 1, a + n + 1, [](segment p, segment q) { return max(p.x1, p.x2) > max(q.x1, q.x2); });
    sort(b + 1, b + m + 1, [](QQ p, QQ q) { return p.x > q.x; });
    j = 1;
    for (int i = 1; i <= n; i++)
    {
        for (; j <= m && b[j].x > max(a[i].x1, a[i].x2); j++)
            if (b[j].dir == 0)
                b[j].aim = a[query(1, 0, k, b[j].y)].num;
        if (a[i].y1 == a[i].y2 && a[i].x1 < a[i].x2)
        {
            int v = query(1, 0, k, a[i].y1);
            if (v)
                add(a[i].num, a[v].num, dist(a[i].x2, a[i].y2, a[v].x2, a[v].y2));
        }
        else
        {
            change(1, 0, k, min(a[i].y1, a[i].y2), max(a[i].y1, a[i].y2), i);
        }
    }
    for (; j <= m; j++)
        if (b[j].dir == 0)
            b[j].aim = a[query(1, 0, k, b[j].y)].num;

    build(1, 0, k);
    sort(a + 1, a + n + 1, [](segment p, segment q) { return min(p.x1, p.x2) < min(q.x1, q.x2); });
    sort(b + 1, b + m + 1, [](QQ p, QQ q) { return p.x < q.x; });
    j = 1;
    for (int i = 1; i <= n; i++)
    {
        for (; j <= m && b[j].x < min(a[i].x1, a[i].x2); j++)
            if (b[j].dir == 2)
                b[j].aim = a[query(1, 0, k, b[j].y)].num;
        if (a[i].y1 == a[i].y2 && a[i].x1 > a[i].x2)
        {
            int v = query(1, 0, k, a[i].y1);
            if (v)
                add(a[i].num, a[v].num, dist(a[i].x2, a[i].y2, a[v].x2, a[v].y2));
        }
        else
        {
            change(1, 0, k, min(a[i].y1, a[i].y2), max(a[i].y1, a[i].y2), i);
        }
    }
    for (; j <= m; j++)
        if (b[j].dir == 2)
            b[j].aim = a[query(1, 0, k, b[j].y)].num;
}
int main()
{
    scanf("%d%d", &n, &k);
    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].num = i;
    }
    scanf("%d", &m);
    for (int i = 1; i <= m; i++)
    {
        scanf("%d%d%s%lld", &b[i].x, &b[i].y, mo, &b[i].t);
        b[i].num = i, b[i].dir = (*mo == 'R' ? 0 : (*mo == 'U' ? 1 : (*mo == 'L' ? 2 : 3)));
    }
    initgraph();
    sort(a + 1, a + n + 1, [](segment p, segment q) { return p.num < q.num; });
    for (int i = 1; i <= n; i++)
    {
        if (head[i])
            fa[i][0] = e[head[i]].to, cost[i][0] = e[head[i]].w;
        else
            cost[i][0] = INFll;
    }
    for (int j = 1; j <= 50; j++)
    {
        for (int i = 1; i <= n; i++)
        {
            fa[i][j] = fa[fa[i][j - 1]][j - 1];
            cost[i][j] = cost[i][j - 1] + cost[fa[i][j - 1]][j - 1];
            if (cost[i][j] > INFll)
                cost[i][j] = INFll;
        }
    }
    for (int i = 1; i <= m; i++)
    {
        int s = b[i].aim, &X = ans[b[i].num][0], &Y = ans[b[i].num][1];
        if (s)
        {
            if (b[i].t > dist(b[i].x, b[i].y, a[s].x2, a[s].y2))
            {
                b[i].t -= dist(b[i].x, b[i].y, a[s].x2, a[s].y2);
                for (int j = 50; j >= 0 && b[i].t > 0; j--)
                {
                    if (b[i].t >= cost[s][j])
                        b[i].t -= cost[s][j], s = fa[s][j];
                }
                b[i].x = a[s].x2, b[i].y = a[s].y2, b[i].dir = DIR(a[s]), s = fa[s][0];
            }
            if (s && b[i].t > DIST(b[i].x, b[i].y, a[s]))
            {
                pair<int, int> mp = MAP(b[i].x, b[i].y, a[s]);
                b[i].t -= DIST(b[i].x, b[i].y, a[s]), b[i].x = mp.first, b[i].y = mp.second, b[i].dir = DIR(a[s]);
            }
        }
        switch (b[i].dir)
        {
        case 0:
            X = min(b[i].x + b[i].t, D(k)), Y = b[i].y;
            break;
        case 1:
            X = b[i].x, Y = min(b[i].y + b[i].t, D(k));
            break;
        case 2:
            X = max(b[i].x - b[i].t, 0ll), Y = b[i].y;
            break;
        case 3:
            X = b[i].x, Y = max(b[i].y - b[i].t, 0ll);
            break;
        }
    }
    for (int i = 1; i <= m; i++)
        printf("%d %d\n", ans[i][0], ans[i][1]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/BlogOfchc1234567890/p/10782936.html