codeforces 295E Yaroslav and Points (线段树)

http://codeforces.com/problemset/problem/295/E

题目大意:在一条水平的直线上有n个点,编号1~n,告诉你每个点的横坐标xi,然后有两个操作:

1:将编号为i的点平移d各单位,d为正往右,否则往左。

2:求处于区间[l,r]之间每一对点的距离之和,即求

思路:还是比较裸的线段树问题,我们在线段树中维护以下值:

num:该区间有多少个点。

sum:该区间点的横坐标之和。

ans :该区间每一对点的距离之和。

有了上面的量,下面关键的一点就是合并,其实很容易,设当前区间为t[p],其左子树为t[ls],右子树为[rs],则:

t[p].sum=t[ls].sum+t[rs].sum

t[p].num=t[ls].num+t[rs].num

t[p].ans=t[rs].sum*t[ls].num-t[rs].num*t[ls].sum+t[ls].ans+t[rs].ans

至于为什么自己推以下应该没问题。

还有就是这道题要先离散化,把可能出现的横坐标值都求出来,离散化之后再建树。然后就没什么了,上代码。

#include 
#include 
#include 
#include 
#define maxn 500010
using namespace std;
#define mid ((t[p].l+t[p].r)>>1)
#define ls (p<<1)
#define rs (ls|1)
#define ll long long
struct tree
{
    int l,r;
    ll sum,ans,num;
}t[maxn<<2];
int a[100010],b[100010],tmp[maxn],aa[maxn];
int ask[100010][3];
int search(int x,int num)
{
    int mi=1,ma=num,Mid;
    while(mi<=ma)
    {
        Mid=(mi+ma)>>1;
        if(aa[Mid]==x)
        return Mid;
        if(aa[Mid]0)
        {
            t[p].num++;
            t[p].ans=0;
            t[p].sum=aa[x];
        }
        else
        {
            t[p].num=0;
            t[p].ans=0;
            t[p].sum=0;
        }
        return;
    }
    if(x>mid)
    change(rs,x,val);
    else
    change(ls,x,val);
    pushup(p);
}
struct node
{
    ll ans,num,sum;
};
node query(int p,int l,int r)
{
    node tt;
    if(t[p].l==l&&t[p].r==r)
    {
        tt.ans=t[p].ans;
        tt.sum=t[p].sum;
        tt.num=t[p].num;
        return tt;
    }
    if(l>mid)
    return query(rs,l,r);
    else if(r<=mid)
    return query(ls,l,r);
    else
    {
        node t1=query(ls,l,mid),t2=query(rs,mid+1,r);
        tt.sum=t1.sum+t2.sum;
        tt.num=t1.num+t2.num;
        tt.ans=t1.ans+t2.ans+t2.sum*t1.num-t1.sum*t2.num;
        return tt;
    }
}
int main()
{
    int n,m,i,num=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        b[i]=a[i];
        tmp[num++]=a[i];
    }
    scanf("%d",&m);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&ask[i][0],&ask[i][1],&ask[i][2]);
        if(ask[i][0]==1)
        {
            b[ask[i][1]]+=ask[i][2];
            tmp[num++]=b[ask[i][1]];
        }
        else
        {
            tmp[num++]=ask[i][1];
            tmp[num++]=ask[i][2];
        }
    }
    sort(tmp,tmp+num);
    aa[1]=tmp[0];
    int sum=1;
    for(i=1;i


 

你可能感兴趣的:(codeforces,数据结构)