XMU 1607 nc與點對距離 【線段樹】

1607: nc與點對距離

Time Limit: 5000 MS  Memory Limit: 512 MB
Submit: 60  Solved: 8
[Submit][Status][Web Board]

Description

nc最近很無聊~所以他總是想各種有趣的問題來打發時間。
nc在地上畫了一條一維座標軸,座標軸上有n個點。第一個點的座標爲 x1,第二個點座標爲 x2,....第n個點的座標爲 xn。他想對這些點進行如下兩種操作:
(1)給定兩個值p和d,將第p個點的座標移動到 xp+d。等價於如下賦值語句xp=xp+d
(2)給定一個區間[l,r],計算在此處區間內,所有點對的距離的和。即要求輸出以下式子的大小:  
請你幫幫他。

Input

第一行包含1個整數n,表示有n個點(1<=n<=10^5)。
第二行包含n個數字,分別表示x1,x2,...xn。(|xi| ≤ 10^9).
第三行包含1個整數m,表示m種操作(1<=m<=10^5),表示有m個詢問。
以下m行,每行表示一個詢問,每一行第一個數爲t:
若t=1,則表示操作(1),其後有兩個數字,分別爲p和d。(其中1<=p<=n, |d|<=1000)
若t=2,則表示操作(2),其後有兩個數字,分別爲l和r。(其中-10^9<=l<=r<=10^9)
輸入保證在任意時刻,都不會出現點xi出現在同一個位置的情況。

Output

每一個操作(2),輸入其答案。

Sample Input

8
36 50 28 -75 40 -60 -95 -48
20
2 -61 29
1 5 -53
1 1 429
1 5 130
2 -101 -71
2 -69 53
1 1 404
1 5 518
2 -101 53
2 50 872
1 1 -207
2 -99 -40
1 7 -389
1 6 -171
1 2 464
1 7 -707
1 1 -730
1 1 560
2 635 644
1 7 -677

Sample Output

176
20
406
1046
1638
156
0

HINT

Source

[Submit][Status][Web Board]


題目鏈接:

  http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1607

題目大意:

  一開始給N個座標x[i],接下來有兩種操作:

  1給定兩個值p和d,將第p個點的座標移動到 xp+d。等價於如下賦值語句xp=xp+d

  2給定一個區間[l,r],計算在此處區間內,所有點對的距離的和。即要求輸出以下式子的大小:  

題目思路:

  【線段樹】

  題目看上去就是線段樹的套路。

  這題由於座標範圍很大,不能直接開數組。可選的方法是離散化或者new。

  (一開始一個節點,表示的區間爲-MAX~MAX,有用到的點就依次往下擴展爲(l,mid)和(mid+1,r),一條樹鏈最多log個節點,所以總結點數爲mlogm)。

  對於操作1,我們先將原先的xp從線段樹中刪除,然後再把xp+d插入線段樹。並進行維護。

  對於操作2,要求解[l,r]的點對和,首先需要記錄幾個值:(以下出現的點表示的是 X座標含在這個區間的點)

    lc,rc表示當前節點的左右兒子,表示的區間爲[l,mid]和[mid+1,r]

    tol表示當前區間內所有出現的點到l的距離和,tor表示當前區間內所有出現的點到r的距離和

    sum表示[l,r]裏出現的點的點對距離和,sz表示[l,r]內出現的點的個數

  維護的時候tol和tor的維護很容易就推出來。sum的維護稍微麻煩點,但是模擬3個點和3個點合併的過程,也還是不難推的。(具體見代碼)

  求解的時候,需要記錄當前這個節點的左右兒子的滿足在[l,r]區間內的tol,tor,sz,sum值,並按照維護的求法求得最終的sum。



/****************************************************
     
    Author : Coolxxx
    Copyright 2017 by Coolxxx. All rights reserved.
    BLOG : http://blog.csdn.net/u010568270
     
****************************************************/
#include<bits/stdc++.h>
#pragma comment(linker,"/STACK:1024000000,1024000000")
#define abs(a) ((a)>0?(a):(-(a)))
#define lowbit(a) (a&(-a))
#define sqr(a) ((a)*(a))
#define mem(a,b) memset(a,b,sizeof(a))
const double EPS=1e-8;
const int J=10;
const int MOD=100000007;
const int MAX=0x7f7f7f7f;
const double PI=3.14159265358979323;
const int N=100004;
using namespace std;
typedef long long LL;
double anss;
LL aans;
int cas,cass;
int n,m,lll,ans;
LL p[N];
struct xxx
{
    LL l,r,sum,tol,tor,sz;
    xxx *lc,*rc;
    xxx()
    {
        l=r=sum=tol=tor=sz=0;
        lc=rc=NULL;
    }
    xxx(LL ll,LL rr)
    {
        l=ll;r=rr;
        sum=tol=tor=sz=0;
        lc=rc=NULL;
    }
    void expand()
    {
        if(lc!=NULL || rc!=NULL)return;
        if(l>=r)return;
        LL mid=(l==r-1)?l:(l+r)/2;
        lc=new xxx(l,mid);
        rc=new xxx(mid+1,r);
    }
    void Insert(LL pos)
    {
        if(pos<l || r<pos)return;
        if(l==r && l==pos)
        {
            sz++;
            return;
        }
        expand();
        lc->Insert(pos);
        rc->Insert(pos);
        maintain();
    }
    void Delete(LL pos)
    {
        if(pos<l || r<pos)return;
        if(l==r && l==pos)
        {
            sz--;
            return;
        }
        lc->Delete(pos);
        rc->Delete(pos);
        maintain();
        if(!lc->sz && !rc->sz)
        {
            delete lc,rc;
            lc=rc=NULL;
        }
    }
    void maintain()
    {
        sz = lc->sz + rc->sz;
        tol = lc->tol + rc->tol + rc->sz * (rc->l - lc->l);
        tor = rc->tor + lc->tor + lc->sz * (rc->r - lc->r);
        sum = lc->sum + rc->sum + lc->sz * rc->tol + rc->sz * lc->tor + lc->sz * rc->sz;  //(rc->l - lc->r)=1;
    }
    LL query(LL a,LL b,LL &num,LL &lsum,LL &rsum)
    {
        if(a<=l && r<=b)
        {
            lsum=tol;
            rsum=tor;
            num=sz;
            return sum;
        }
        if(b<l || r<a)
        {
            lsum=rsum=num=0;
            return 0;
        }
        expand();
        LL lnum,rnum,llsum,rlsum,lrsum,rrsum;
        lsum = lc->query(a,b,lnum,llsum,lrsum);
        rsum = rc->query(a,b,rnum,rlsum,rrsum);
         
        num = lnum + rnum;
        aans = lsum + rsum + rnum * lrsum + lnum * rlsum + lnum * rnum;
        lsum = llsum + rlsum + rnum * (rc->l - lc->l);
        rsum = lrsum + rrsum + lnum * (rc->r - lc->r);
        return aans;
    }
};
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("1.txt","r",stdin);
//  freopen("2.txt","w",stdout);
    #endif
    int i,j,k;
    LL x,y,z,xx,yy;
//  for(scanf("%d",&cass);cass;cass--)
//  for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
//  while(~scanf("%s",s))
    while(~scanf("%d",&n))
    {
        xxx *t=new xxx(-2e9,2e9);
        for(i=1;i<=n;i++)
        {
            scanf("%lld",&p[i]);
            t->Insert(p[i]);
        }
        scanf("%d",&m);
         
        for(i=1;i<=m;i++)
        {
            scanf("%d%lld%lld",&cass,&x,&y);
            if(cass==1)
            {
                t->Delete(p[x]);
                p[x]+=y;
                t->Insert(p[x]);
            }
            else
                printf("%lld\n",t->query(x,y,z,xx,yy));
        }
        delete t;
    }
    return 0;
}
/*
//
 
//
*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章