islands的难题—线段是单点更新
来源:互联网 发布:新手学炒股 知乎 编辑:程序博客网 时间:2024/06/03 00:20
Description
最近islands遇到一个难题,他想请人帮他解决。给一个数列a1,a2……an。有m个操作,每个操作是下面2种之一。
第1种操作是询问区间[l,r]上的值。
第2种操作是使得第k个数加上v。
Input
首先输入T表示测试数据组数(T<=5)每组数据第一行输入n,m(n,m<=100000)表示n个数和m个操作。接下来1行输入n个数,表示ai。(0<=a[i]<=100000)接下来m行每行输入d(0或者1),l,r。d=0表示第1操作 ( 0 < l <= r <= n),表示询问[l,r]上的答案。d=1表示第2种操作( 0 < l <= n, 0 <= r <= 1000),表示a[l]加上r。
Output
对于每组测试数据首先输出一行“Case #x:”(不包括冒号)x表示第x组数据对于m个操作,如果是1操作输出一行表示对应答案。
15 51 2 3 4 50 1 50 3 41 5 10 1 50 3 4
Case #1:55116011
首先预处理sum1[i]=a1*1+a2*2+…+ai*i;
sum2[i]=a1+a2+….ai;
对于查询[l,r]
ans=sum1[r]-sum1[l-1]-(l-1)*(sum2[r]-sum2[l-1]);
对于单点更新某个点的a[i],可以用线段树或者树状数组等数据结构方法维护。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
#define nn 100001
#define ll long long
struct node
{
ll le,ri;
ll sum1;
ll sum2;
}tree[nn*5];
ll val11[nn];
ll val22[nn];
void pushup(ll id)
{
tree[id].sum1=tree[id*2].sum1+tree[id*2+1].sum1;
tree[id].sum2=tree[id*2].sum2+tree[id*2+1].sum2;
}
void build(ll id,ll l,ll r)
{
tree[id].le=l;
tree[id].ri=r;
if(l==r)
{
tree[id].sum1=val11[l];
tree[id].sum2=val22[l];
return ;
}
ll mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
pushup(id);
}
void update(ll id,ll pos,ll p,ll q)
{
if(tree[id].le==tree[id].ri)
{
tree[id].sum1=tree[id].sum1+p;
tree[id].sum2=tree[id].sum2+q;
return ;
}
ll mid=(tree[id].le+tree[id].ri)/2;
if(pos<=mid)
update(id*2,pos,p,q);
else
update(id*2+1,pos,p,q);
pushup(id);
}
ll query1(ll id,ll l,ll r)
{
if(tree[id].le>=l&&tree[id].ri<=r)
{
return tree[id].sum1;
}
ll mid=(tree[id].le+tree[id].ri)/2;
ll ans=0;
if(l<=mid)
ans+= query1(id*2,l,r);
if(r>mid)
ans+= query1(id*2+1,l,r);
return ans;
}
ll query2(ll id,ll l,ll r)
{
if(tree[id].le>=l&&tree[id].ri<=r)
{
return tree[id].sum2;
}
ll mid=(tree[id].le+tree[id].ri)/2;
ll ans=0;
if(l<=mid)
ans+= query2(id*2,l,r);
if(r>mid)
ans+= query2(id*2+1,l,r);
return ans;
}
int main()
{
ll i,j;
ll m,n;
// ll sum1[nn];
ll sum[nn];
ll t;
while(scanf("%lld",&t)!=EOF)
{
for(ll kk=1;kk<=t;kk++)
{
memset(val11,0,sizeof(val11));
memset(val22,0,sizeof(val22));
scanf("%lld %lld",&n,&m);
ll d,l,r;
for(i=1;i<=n;i++)
{
scanf("%lld",&val11[i]);
val22[i]=val11[i]*i;
}
build(1,1,n);
ll hh=0;
ll cntsum=0;
for(ll o=1;o<=m;o++)
{
scanf("%lld %lld %lld",&d,&l,&r);
if(d==1)
{
update(1,l,r,r*l);
}
else if(d==0)
{
ll a1,a2;
ll b1,b2;
ll gg;
a1=query1(1,1,r);
a2=query1(1,1,l-1);
b1=query2(1,1,r);
b2=query2(1,1,l-1);
// printf("** %lld %lld %lld %lld\n",a1,a2,b1,b2);
gg=b1-b2-(l-1)*(a1-a2);
sum[hh++]=gg;
}
}
printf("Case #%lld:\n",kk);
for(j=0;j<hh;j++)
printf("%lld\n",sum[j]);
}
}
}
- islands的难题—线段是单点更新
- hdu4046 不错的线段树单点更新
- hdu1754 简单的线段树单点更新
- Node:线段树的单点更新
- 线段树 单点更新
- 线段树单点更新
- 线段树 单点更新
- 单点更新线段树
- 线段树单点更新
- 线段树单点更新
- 线段树 单点更新
- 线段树 单点更新
- 线段树单点更新
- 线段树 单点更新
- 单点更新线段树
- 线段树单点更新
- 线段树,单点更新
- HDOJ 4399 —— 线段树单点更新&单点查询
- 第四章作业补+排序+查询
- Linux\Windows下vim配置
- BestCoder Round #41 -- (A,B)
- 根据前序和中序遍历求后序 /后序和中序求前序
- override中super的用法
- islands的难题—线段是单点更新
- java 线程安全
- 初学者必知的Python中优雅的用法
- 数字
- 配置SSH无密码访问及Linux热键、重启、kill进程
- 数组
- 理解MySQL——索引与优化
- Android Service 使用
- 圣诞老人的礼物-Santa Clau’s Gifts