XMU 1607 nc与点对距离 线段树
Posted Coolxxx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 -677Sample Output
176
20
406
1046
1638
156
0HINT
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\n",t->query(x,y,z,xx,yy)); 145 } 146 delete t; 147 } 148 return 0; 149 } 150 /* 151 // 152 153 // 154 */
以上是关于XMU 1607 nc与点对距离 线段树的主要内容,如果未能解决你的问题,请参考以下文章