Fenwick tree and the tree line (c)

Find the law title

1. helical polyline

Helical polyline as shown in FIG whole through all points in the plane exactly once.

p1.png

For integer point  ( X- , the Y ) , which we define the distance from the origin  D I S ( X- , the Y )  from the origin to  ( X- , the Y )  length of the helical segments.

E.g.  D I S ( 0 , . 1 ) = . 3 , D I S ( - 2 , - . 1 ) = . 9

The whole point is given the coordinates  ( X- , the Y ) , you can calculate  D I S ( X- , the Y ) it?

Input Format

It contains two integers  X- , the Y .

Output Format

Output an integer representing  D I S ( X- , the Y ) .

data range

109X,Y109

Sample input:

0 1

Sample output:

3
解题思路:这是一道找规律题,我们可以将整个坐标都用距离标识一下,如下图

 

 We look at x> = 0 && y> = 0: if x> = y, dis = (2 * x) * (2 * x) + (xy), if x <y, dis = (2 * y) * ( 2 * y) - (yx)

Look at x <0 && y> 0: x absolute value, if x> = y, dis = (2 * x-1) * (2 * x) - (xy), if x <y, dis = (2 * y -1) * (2 * y) + (yx)

再看x<=0&&y<=0:x取绝对值,y取绝对值,若x>=y&&x!=0&&y!=0,dis=(2*x-1)*(2*x-1)+(x-y),若x<y&&x!=0&&y!=0,dis=(2*y+1)*(2*y+1)-(y+1-x)

其中需要特殊考虑x和y的负半轴,x!=0&&y==0,dis=(2*x-1)*(2*x-1)+(x-1),当x==0&&y!=0,dis=(2*y+1)*(2*y+1)-(y+1)

再看x>0&&y<0时:y取绝对值,当x<=y,dis=(2*y+1)*(2*y)+(y-x),当x>y时,dis=(2*x+1)*(2*x)-(x-y)

代码:

#include<iostream>
using namespace std;
typedef long long ll;
int main()
{
    ll x,y,i,j;
    cin>>x>>y;
    if(x>=0&&y>=0)
    {
        if(y>=x)
            cout<<(2*y)*(2*y)-(y-x)<<endl;
        else if(y<x)
            cout<<(2*x)*(2*x)+(x-y)<<endl;
    }
    else if(x<0&&y>0)
    {
        x=-x;
        if(x>=y)
            cout<<(2*x-1)*(2*x)-(x-y)<<endl;
        else if(x<y)
            cout<<(2*y-1)*(2*y)+(y-x)<<endl;
    }
    else if(x<=0&&y<=0)
    {
        x=-x;y=-y;
        if(x>=y&&x!=0&&y!=0)
        {
            cout<<(2*x-1)*(2*x-1)+(x-y)<<endl;
        }
        else if(x<y&&x!=0&&y!=0)
            cout<<(2*y+1)*(2*y+1)-(y+1-x)<<endl;
        else if(x!=0&&y==0)
            cout<<(2*x-1)*(2*x-1)+(x-1)<<endl;
        else if(x==0&&y!=0)
            cout<<(2*y+1)*(2*y+1)-(y+1)<<endl;
    }
    else if(x>0&&y<0)
    {
        y=-y;
        if(x<=y)
            cout<<(2*y+1)*(2*y)+(y-x)<<endl;
        else if(x>y)
            cout<<(2*x+1)*(2*x)-(x-y)<<endl;
    }
    return 0;
}

 

(二)差分

1.差分矩阵

输入一个n行m列的整数矩阵,再输入q个操作,每个操作包含五个整数x1, y1, x2, y2, c,其中(x1, y1)和(x2, y2)表示一个子矩阵的左上角坐标和右下角坐标。

每个操作都要将选中的子矩阵中的每个元素的值加上c。

请你将进行完所有操作后的矩阵输出。

输入格式

第一行包含整数n,m,q。

接下来n行,每行包含m个整数,表示整数矩阵。

接下来q行,每行包含5个整数x1, y1, x2, y2, c,表示一个操作。

输出格式

共 n 行,每行 m 个整数,表示所有操作进行完毕后的最终矩阵。

数据范围

1n,m1000
1q100000
1x1x2n
1y1y2m
1000c1000
10001000

输入样例:

3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1

输出样例:

2 3 4 1
4 3 4 1
2 2 2 2
解题思路:差分矩阵是二维的,之前的差分数组是一维的,他的解题思路与一维的思路是一样的
核心:a[N][N],b[N][N],a数组是b数组的前缀和
因此要在(x1,y1),(x2,y2)之间加上一个数,则需要将

b[x1][y1]+=c;
b[x1][y2+1]-=c;
b[x2+1][y1]-=c;
b[x2+1][y2+1]+=c;

这样才能满足差分矩阵的要求

代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1010;
int n,m,q;
int a[N][N],b[N][N];

void insert(int x1,int y1,int x2,int y2,int c)
{
    b[x1][y1]+=c;
    b[x1][y2+1]-=c;
    b[x2+1][y1]-=c;
    b[x2+1][y2+1]+=c;
}
int main()
{
    int i,j;
    scanf("%d%d%d",&n,&m,&q);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            insert(i,j,i,j,a[i][j]);
    while(q--)
    {
        int x1,y1,x2,y2,c;
        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);
        insert(x1,y1,x2,y2,c);
    }
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+b[i][j];
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
            cout<<a[i][j]<<" ";
        cout<<endl;
    }
    return 0;
}

 

(三)线段树

1.油漆面积

X星球的一批考古机器人正在一片废墟上考古。

该区域的地面坚硬如石、平整如镜。

管理人员为方便,建立了标准的直角坐标系。

每个机器人都各有特长、身怀绝技。

它们感兴趣的内容也不相同。

经过各种测量,每个机器人都会报告一个或多个矩形区域,作为优先考古的区域。

矩形的表示格式为 (x1,y1,x2,y2),代表矩形的两个对角点坐标。

为了醒目,总部要求对所有机器人选中的矩形区域涂黄色油漆。

小明并不需要当油漆工,只是他需要计算一下,一共要耗费多少油漆。

其实这也不难,只要算出所有矩形覆盖的区域一共有多大面积就可以了。

注意,各个矩形间可能重叠。

输入格式

第一行,一个整数 n,表示有多少个矩形。

接下来的 n行,每行有 4 个整数 x1,y1,x2,y2,空格分开,表示矩形的两个对角顶点坐标。

输出格式

一行一个整数,表示矩形覆盖的总面积。

数据范围

1n10000
0x1,x2,y2,y210000
数据保证 x1<x2 且 y1<y2

输入样例1:

3
1 5 10 10
3 1 20 20
2 7 15 17

输出样例1:

340

输入样例2:

3
5 2 10 6
2 7 12 10
8 1 15 15

输出样例2:

128
代码:
题解稍后补上
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=10010;
int n;
struct Segment
{
    int x,y1,y2;
    int k;
    bool operator< (const Segment &t)const
    {
        return x<t.x;
    }
}seg[N*2];
struct node
{
    int l,r;
    int len,cnt;
}tr[N*4];
void pushup(int u)
{
    if(tr[u].cnt>0)
        tr[u].len=tr[u].r-tr[u].l+1;
    else if(tr[u].l==tr[u].r)
        tr[u].len=0;
    else
        tr[u].len=tr[u<<1].len+tr[u<<1|1].len;
}
void build(int u,int l,int r)
{
    tr[u]={l,r};
    if(l==r)
        return;
    int mid=l+r>>1;
    build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
void modify(int u,int l,int r,int k)
{
    if(tr[u].l>=l&&tr[u].r<=r)
    {
        tr[u].cnt+=k;
        pushup(u);
    }
    else
    {
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)
            modify(u<<1,l,r,k);
        if(r>mid)
            modify(u<<1|1,l,r,k);
        pushup(u);
    }
}
int main()
{
    cin>>n;
    int m=0;
    for(int i=0;i<n;i++)
    {
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        seg[m++]={x1,y1,y2,1};
        seg[m++]={x2,y1,y2,-1};
    }
    sort(seg,seg+m);
    build(1,0,10000);
    int res=0;
    for(int i=0;i<m;i++)
    {
        if(i>0)
            res + = tr [ 1 ] .len (out [i] .x-up [i- 1 ] .x);
        modify ( 1 , out [i] .y1, out [i] .y2- 1 , out [i] .k);
    }
    printf("%d",res);
    return 0;
}

 



Guess you like

Origin www.cnblogs.com/xiaofengzai/p/12240083.html