zoukankan      html  css  js  c++  java
  • Codeforces 331D

    题意

    (b*b) 的平面上有 (n) 条有向线段,它们长度 (≥1) ,与坐标轴平行,且任意两条互不相交。现在有 (m) 个询问,每个询问表示从 ((x,y)) 开始,初始方向为 (dir) ,走 (t) 步到达的位置。如果超出平面范围则输出从哪个位置超出的。((n,m,ble 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
    ",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
    ", ans[i][0], ans[i][1]);
    	return 0;
    }
    
  • 相关阅读:
    数据结构学习8——二叉树的销毁
    单链表的反向
    LNK4098: 默认库“MSVCRT”与其他库的使用冲突
    动态链接库(VC_Win32)
    注册表操作(VC_Win32)
    消息钩子与定时器(VC_Win32)
    套接字编程(VC_Win32)
    线程概述,优先级,睡眠,创建及终止(VC_Win32)
    进程通信(VC_Win32)
    进程概述及创建,终止(VC_Win32)
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/10782936.html
Copyright © 2011-2022 走看看