2017计蒜之道复赛-Windows 画图

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/algzjh/article/details/73000250

在 Windows 的“画图”工具里,可以绘制各种各样的图案。可以把画图当做一个标准的二维平面,在其上先后绘制了 nn 条颜色互不相同的线段。

按绘制的时间顺序,从先到后把线段依次编号为 11 到 nn。第 ii 条线段的两个端点分别为 (xa_i,ya_i)(xai,yai) 和 (xb_i,yb_i)(xbi,ybi),线段的粗细忽略不计。后绘制的线段不会改变之前绘制的线段的位置。

请写一个程序,回答 qq 组询问,每组询问给出一个坐标 (x_i,y_i)(xi,yi),你需要算出在这个点上最后绘制的线段编号。

输入格式

第一行包含两个正整数 n,m(1\leq n\leq 80000,1\leq m\leq 250)n,m(1n80000,1m250),分别表示线段的数目以及坐标的最大取值(下面会具体说明)。

接下来 nn 行,每行输入四个正整数 xa_i,ya_i,xb_i,yb_ixai,yai,xbi,ybi (1\leq xa_i,ya_i,xb_i,yb_i\leq m,(1xai,yai,xbi,ybim, (xa_i,ya_i)\neq(xb_i,yb_i))(xai,yai)(xbi,ybi)),依次表示每条线段两个端点的坐标。

接下来一行,输入一个正整数 q(1\leq q\leq 62500)q(1q62500),表示询问的组数。

接下来 qq 行,每行输入两个正整数 x_i,y_i(1\leq x_i,y_i\leq m)xi,yi(1xi,yim),分别表示每组询问的坐标。

输出格式

输出 qq 行,每行一个整数,表示该位置最上面(最后绘制)的线段的编号。

若该点上不存在线段,请输出 00

样例解释

样例对应题目描述中的图。

样例输入

5 8
2 5 5 2
5 2 3 8
8 4 1 4
2 2 5 8
8 7 4 1
4
3 4
5 2
6 4
3 5

样例输出

4
2
5
0


题目大意:中文题

解题思路:模拟一下,紫书上有线段上整点分析,用gcd

官方题解:

注意到线段上点数为 O(m)O(m),故对于每个线段,暴力枚举所有位于线段上的整点即可。

首先特判掉水平和竖直的线段,然后对于坐标差分别为 dxdx 和 dydy 的线段,令 d=\gcd(dx,dy)d=gcd(dx,dy),那么 xx 每隔 \frac{dx}{d}ddx 个,yy 每隔 \frac{dy}{d}ddy 个就是整点,由此方法可以很方便地枚举所有整点。



#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
#include<string>
using namespace std;
typedef long long LL;
const int MOD=100003;
int n,m,q;
int G[260][260];

int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}

struct seg
{
    int sx,sy,tx,ty;
    int id;
}s[80005];

void solve(int i)
{
    double ty;
    if(s[i].sx==s[i].tx)
    {
        if(s[i].sy<s[i].ty)
        {
            for(int j=s[i].sy;j<=s[i].ty;j++)
                G[s[i].sx][j]=s[i].id;
        }else
        {
            for(int j=s[i].ty;j<=s[i].sy;j++)
                G[s[i].sx][j]=s[i].id;
        }
    }else if(s[i].sx<s[i].tx)
    {
        double a=(double)(s[i].ty-s[i].sy)/(s[i].tx-s[i].sx);
        double c=-a*s[i].sx+s[i].sy;
        int f1=s[i].ty-s[i].sy;
        int f2=s[i].tx-s[i].sx;
        for(int j=s[i].sx+1;j<=s[i].tx;j++)
        {
            ty=a*j+c;
            if(gcd(f1*(j-s[i].sx),f2)==f2)
                G[j][f1*(j-s[i].sx)/(f2)+s[i].sy]=s[i].id;
            //if((int)ty==ty)
        }
    }else
    {
        double a=(double)(s[i].sy-s[i].ty)/(s[i].sx-s[i].tx);
        double c=-a*s[i].tx+s[i].ty;
        int f1=s[i].sy-s[i].ty;
        int f2=s[i].sx-s[i].tx;
        for(int j=s[i].tx+1;j<=s[i].sx;j++)
        {
            ty=a*j+c;
            if(gcd(f1*(j-s[i].tx),f2)==f2)
                G[j][f1*(j-s[i].tx)/f2+s[i].ty]=s[i].id;
            //if((int)ty==ty)
        }
    }
}

int main()
{
    while(cin>>n>>m)
    {
        memset(G,0,sizeof(G));
        int sx,sy,tx,ty;
        for(int i=1;i<=n;i++)
        {
            cin>>sx>>sy>>tx>>ty;
            s[i].sx=sx;
            s[i].sy=sy;
            s[i].tx=tx;
            s[i].ty=ty;
            s[i].id=i;
            G[sx][sy]=i;
            G[tx][ty]=i;
            solve(i);
        }
        cin>>q;
        int x,y;
        for(int i=1;i<=q;i++)
        {
            cin>>x>>y;
            cout<<G[x][y]<<endl;
        }
    }
    return 0;
}


阅读更多

扫码向博主提问

algzjh

非学,无以致疑;非问,无以广识
  • 擅长领域:
  • ACM
去开通我的Chat快问
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页