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

by cjf

[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\n",t->query(x,y,z,xx,yy));
145         }
146         delete t;
147     }
148     return 0;
149 }
150 /*
151 //
152
153 //
154 */

时间: 2024-10-13 04:45:38

XMU 1607 nc与点对距离 【线段树】的相关文章

【BZOJ3730】震波 动态树分治+线段树

[BZOJ3730]震波 Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动.接下来你需要在线处理M次操作:0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和.1 x y 表示第x个城市的价值变成了y.为了体现程序的在

bzoj2006 [ NOI2010 ] &amp;&amp; bzoj3784 --点分治+线段树+堆

bzoj2006: 定义一个四元组{x,l,r,w},表示左端点在x,右端点在[l,r]的超级和弦的最大美妙度在将w作为右端点时取到,w可以用前缀和+线段树/ST表求出. 对于每个i,我们将{i,i+L-1,i+R-1,w}放入一个大根堆中,每次取出美妙度最大的一个加到答案中,并将{i,l,w-1,x},{i,w+1,r,x}放入堆中. 这样就相当于将左端点在i.右端点在w的超级和弦去掉.做k次就可以了. 代码: 1 #include<iostream> 2 #include<cstdi

[poj2104]可持久化线段树入门题(主席树)

解题关键:离线求区间第k小,主席树的经典裸题: 对主席树的理解:主席树维护的是一段序列中某个数字出现的次数,所以需要预先离散化,最好使用vector的erase和unique函数,很方便:如果求整段序列的第k小,我们会想到离散化二分和线段树的做法, 而主席树只是保存了序列的前缀和,排序之后,对序列的前缀分别做线段树,具有差分的性质,因此可以求任意区间的第k小,如果主席树维护索引,只需要求出某个数字在主席树中的位置,即为sort之后v中的索引:若要求第k大,建树时反向排序即可 1 #include

HDU1832 二维线段树求最值(模板)

Luck and Love Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 50 Accepted Submission(s): 20   Problem Description 世界上上最远的距离不是相隔天涯海角而是我在你面前可你却不知道我爱你                ―― 张小娴 前段日子,枫冰叶子给Wiskey做了个征婚启事,聘

数据结构(括号序列,线段树):ZJOI 2007 捉迷藏

[题目描述] Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达. 游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯.在起初的时候,所有的灯都没有被打开.每一次,孩子们只会躲 藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯或者关闭某个房间的电灯.为了评估某一次

HDU1394 Minimum Inversion Number 线段树+数学

Problem Description The inversion number of a given number sequence a1, a2, -, an is the number of pairs (ai, aj) that satisfy i < j and ai > aj. For a given sequence of numbers a1, a2, -, an, if we move the first m >= 0 numbers to the end of the

hdu4521 小明系列问题——小明序列(LIS变种 (线段树+单点更新解法))

链接: huangjing 题目:中文题目 思路: 这个题目如果去掉那个距离大于d的条件,那么必然是一个普通的LIS,但是加上那个条件后就变得复杂了.用dp的解法没有看懂,我用的线段树的解法...就是采用延迟更新的做法,用为距离要大于d啊,所以我们在循环到第i的时候,就对(i-d-1)这个点进行更新,因为如果在(i-d-1)这个点更新了,会对后面的造成影响,然后线段树的tree[]数组存的是以i结尾的最长lis,那么每次询问的时候就找最大的tree[]就可以了... 代码: 小明系列问题--小明

hdu 4973 A simple simulation problem.(线段树)

http://acm.hdu.edu.cn/showproblem.php?pid=4973 有两种操作 D l r 将[l,r]区间翻倍 Q l r询问[l,r]中相同数字出现的最多次数 比赛的时候脑子太乱了,没有想到怎么做.发现每次翻倍序列的长度都在变化,区间对应的数也在变,没有思路. 但是静下心来想一想,思路还是挺清晰的. 无论怎么翻倍,序列中的数都是连续的,范围是1~n.可以拿一个数组来记录每个数出现的次数,当更新或询问区间[l,r]时,可以利用其前缀和找到区间[l,r]对应的数字分别是

51nod 1272 思维/线段树

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1272 1272 最大距离 题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 关注 给出一个长度为N的整数数组A,对于每一个数组元素,如果他后面存在大于等于该元素的数,则这两个数可以组成一对.每个元素和自己也可以组成一对.例如:{5, 3, 6, 3, 4, 2},可以组成11对,如下(数字为下标):