codeforces 295E Yaroslav and Points (线段树)
来源:互联网 发布:购物商城app源码 编辑:程序博客网 时间:2024/05/16 05:01
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 <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#define maxn 500010using namespace std;#define mid ((t[p].l+t[p].r)>>1)#define ls (p<<1)#define rs (ls|1)#define ll long longstruct 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]<x) mi=Mid+1; else ma=Mid-1; }}void pushup(int p){ 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;}void build(int p,int l,int r){ t[p].l=l,t[p].r=r,t[p].ans=t[p].sum=t[p].num=0; if(l==r) return; build(ls,l,mid); build(rs,mid+1,r);}void change(int p,int x,int val){ if(t[p].l==t[p].r) { if(val>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<num;i++) { if(tmp[i]!=tmp[i-1]) aa[++sum]=tmp[i]; } //for(i=1;i<=sum;i++) //printf("%d %d\n",i,aa[i]); build(1,1,sum); for(i=1;i<=n;i++) { int po=search(a[i],sum); change(1,po,1); } for(i=1;i<=m;i++) { if(ask[i][0]==1) { int po=search(a[ask[i][1]],sum); change(1,po,-1); a[ask[i][1]]+=ask[i][2]; po=search(a[ask[i][1]],sum); change(1,po,1); //printf("%d\n",po); } else { int l=search(ask[i][1],sum),r=search(ask[i][2],sum); node an=query(1,l,r); //printf("%d %d\n",l,r); printf("%I64d\n",an.ans); } } return 0;}
- codeforces 295E Yaroslav and Points (线段树)
- Yaroslav and Points CF 295E
- CF 295E Yaroslav and Points(Splay)
- CF 295E Yaroslav and Points(Splay)
- codeforces 258-E. Little Elephant and Tree 线段树,离线
- Codeforces 580E Kefa and Watch 线段树+双值Hash
- Codeforces #321 E. Kefa and Watch (线段树、哈希)
- codeforces 321# E. Kefa and Watch (线段树+字符串hash)
- Codeforces 580E Kefa and Watch 线段树
- codeforces 580 E. Kefa and Watch (字符串hash + 线段树)
- codeforces 381E Sereja and Brackets(线段树)
- Codeforces 381E Sereja and Brackets(线段树)
- codeforces E. Trains and Statistic 线段树优化dp
- codeforces 675-E Trains and Statistic 线段树+dp
- [Codeforces goodbye2016] E.New Year and Old Subsequence 线段树
- codeforces 580 E. Kefa and Watch(hash+线段树)
- Codeforces 712E Memory And Casinos 概率+线段树
- CodeForces 580 E.Kefa and Watch(hash+线段树)
- C语言的标准
- opencv中关于reshape, repeat初步认识
- debian下儿QT4编程环境的建立
- Centos IP、DNS设置
- 我理解的Linux文件结构
- codeforces 295E Yaroslav and Points (线段树)
- C# 异步编程---IAsyncResult 接口
- MySQL的information_schema的介绍
- APP如何推广
- POJ 2516 Minimum Cost
- “每日小记”之由来
- 优化Android默认的状态栏
- 敏捷开发的26条至理名言
- mac http2.4.4