• 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。

      

      1 /****************************************************
      2      
      3     Author : Coolxxx
      4     Copyright 2017 by Coolxxx. All rights reserved.
      5     BLOG : http://blog.csdn.net/u010568270
      6      
      7 ****************************************************/
      8 #include<bits/stdc++.h>
      9 #pragma comment(linker,"/STACK:1024000000,1024000000")
     10 #define abs(a) ((a)>0?(a):(-(a)))
     11 #define lowbit(a) (a&(-a))
     12 #define sqr(a) ((a)*(a))
     13 #define mem(a,b) memset(a,b,sizeof(a))
     14 const double EPS=1e-8;
     15 const int J=10;
     16 const int MOD=100000007;
     17 const int MAX=0x7f7f7f7f;
     18 const double PI=3.14159265358979323;
     19 const int N=100004;
     20 using namespace std;
     21 typedef long long LL;
     22 double anss;
     23 LL aans;
     24 int cas,cass;
     25 int n,m,lll,ans;
     26 LL p[N];
     27 struct xxx
     28 {
     29     LL l,r,sum,tol,tor,sz;
     30     xxx *lc,*rc;
     31     xxx()
     32     {
     33         l=r=sum=tol=tor=sz=0;
     34         lc=rc=NULL;
     35     }
     36     xxx(LL ll,LL rr)
     37     {
     38         l=ll;r=rr;
     39         sum=tol=tor=sz=0;
     40         lc=rc=NULL;
     41     }
     42     void expand()
     43     {
     44         if(lc!=NULL || rc!=NULL)return;
     45         if(l>=r)return;
     46         LL mid=(l==r-1)?l:(l+r)/2;
     47         lc=new xxx(l,mid);
     48         rc=new xxx(mid+1,r);
     49     }
     50     void Insert(LL pos)
     51     {
     52         if(pos<l || r<pos)return;
     53         if(l==r && l==pos)
     54         {
     55             sz++;
     56             return;
     57         }
     58         expand();
     59         lc->Insert(pos);
     60         rc->Insert(pos);
     61         maintain();
     62     }
     63     void Delete(LL pos)
     64     {
     65         if(pos<l || r<pos)return;
     66         if(l==r && l==pos)
     67         {
     68             sz--;
     69             return;
     70         }
     71         lc->Delete(pos);
     72         rc->Delete(pos);
     73         maintain();
     74         if(!lc->sz && !rc->sz)
     75         {
     76             delete lc,rc;
     77             lc=rc=NULL;
     78         }
     79     }
     80     void maintain()
     81     {
     82         sz = lc->sz + rc->sz;
     83         tol = lc->tol + rc->tol + rc->sz * (rc->l - lc->l);
     84         tor = rc->tor + lc->tor + lc->sz * (rc->r - lc->r);
     85         sum = lc->sum + rc->sum + lc->sz * rc->tol + rc->sz * lc->tor + lc->sz * rc->sz;  //(rc->l - lc->r)=1;
     86     }
     87     LL query(LL a,LL b,LL &num,LL &lsum,LL &rsum)
     88     {
     89         if(a<=l && r<=b)
     90         {
     91             lsum=tol;
     92             rsum=tor;
     93             num=sz;
     94             return sum;
     95         }
     96         if(b<l || r<a)
     97         {
     98             lsum=rsum=num=0;
     99             return 0;
    100         }
    101         expand();
    102         LL lnum,rnum,llsum,rlsum,lrsum,rrsum;
    103         lsum = lc->query(a,b,lnum,llsum,lrsum);
    104         rsum = rc->query(a,b,rnum,rlsum,rrsum);
    105          
    106         num = lnum + rnum;
    107         aans = lsum + rsum + rnum * lrsum + lnum * rlsum + lnum * rnum;
    108         lsum = llsum + rlsum + rnum * (rc->l - lc->l);
    109         rsum = lrsum + rrsum + lnum * (rc->r - lc->r);
    110         return aans;
    111     }
    112 };
    113 int main()
    114 {
    115     #ifndef ONLINE_JUDGE
    116     freopen("1.txt","r",stdin);
    117 //  freopen("2.txt","w",stdout);
    118     #endif
    119     int i,j,k;
    120     LL x,y,z,xx,yy;
    121 //  for(scanf("%d",&cass);cass;cass--)
    122 //  for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
    123 //  while(~scanf("%s",s))
    124     while(~scanf("%d",&n))
    125     {
    126         xxx *t=new xxx(-2e9,2e9);
    127         for(i=1;i<=n;i++)
    128         {
    129             scanf("%lld",&p[i]);
    130             t->Insert(p[i]);
    131         }
    132         scanf("%d",&m);
    133          
    134         for(i=1;i<=m;i++)
    135         {
    136             scanf("%d%lld%lld",&cass,&x,&y);
    137             if(cass==1)
    138             {
    139                 t->Delete(p[x]);
    140                 p[x]+=y;
    141                 t->Insert(p[x]);
    142             }
    143             else
    144                 printf("%lld
    ",t->query(x,y,z,xx,yy));
    145         }
    146         delete t;
    147     }
    148     return 0;
    149 }
    150 /*
    151 //
    152  
    153 //
    154 */
    View Code
  • 相关阅读:
    软工实践寒假作业(2/2)
    软工实践寒假作业(1/2)
    个人作业——软件工程实践总结&个人技术博客
    个人技术总结——postman的接口请求
    个人作业——软件评测
    结对第二次作业——某次疫情统计可视化的实现
    结对第一次—疫情统计可视化(原型设计)
    软工实践寒假作业(2/2)
    软工实践寒假作业(1/2)
    个人作业——软件工程实践总结&个人技术博客
  • 原文地址:https://www.cnblogs.com/Coolxxx/p/6753475.html
Copyright © 2020-2023  润新知