樹狀數組與線段樹(三)

找規律題node

1.螺旋折線ios

以下圖所示的螺旋折線通過平面上全部整點剛好一次。數組

p1.png

對於整點 (X,Y),咱們定義它到原點的距離 dis(X,Y) 是從原點到 (X,Y) 的螺旋折線段的長度。ui

例如 dis(0,1)=3,dis(2,1)=9
atom

給出整點座標 (X,Y),你能計算出 dis(X,Y)嗎?spa

輸入格式

包含兩個整數 X,Ycode

輸出格式

輸出一個整數,表示 dis(X,Y)xml

數據範圍

109X,Y109
blog

輸入樣例:

0 1

輸出樣例:

3
解題思路:這是一道找規律題,咱們能夠將整個座標都用距離標識一下,以下圖

 

 咱們先看x>=0&&y>=0時:若x>=y,dis=(2*x)*(2*x)+(x-y),若x<y,dis=(2*y)*(2*y)-(y-x)ci

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

再看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*(seg[i].x-seg[i-1].x);
        modify(1,seg[i].y1,seg[i].y2-1,seg[i].k);
    }
    printf("%d",res);
    return 0;
}
相關文章
相關標籤/搜索