线段树(区间修改,单点查询)
2017-11-03 16:12
429 查看
题目链接:https://vjudge.net/contest/196267#problem/B
题号:zoj-3284
题目大意:就是给你一个矩阵,让你实现一些修改和查询操作
题目思路:建立两个线段树,不细说
补充:
区间修改区间求求和:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include
bfef
<algorithm>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#define ri(n) scanf("%d",&n)
#define oi(n) printf("%d\n",n)
#define rl(n) scanf("%lld",&n)
#define ol(n) printf("%lld\n",n)
#define rep(i,l,r) for(i=l;i<=r;i++)
#define rep1(i,l,r) for(i=l;i<r;i++)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int epg=10-8;
struct node
{
int l,r;
ll add,sum;
}tr[100010<<2];
ll a[100010<<2];
void build(node *t,int l,int r,int pos)
{
t[pos].l=l;
t[pos].r=r;
t[pos].add=0;
if(l==r)
{
t[pos].sum=a[l];
return;
}
int mid=(t[pos].l+t[pos].r)>>1;
//int mid=(l+r)>>1;
build(t,l,mid,pos<<1);
build(t,mid+1,r,pos<<1|1);
t[pos].sum=t[pos<<1].sum+t[pos<<1|1].sum;
}
void pushdown(node *t,int pos)
{
if(t[pos].add!=0)
{
t[pos<<1].add+=t[pos].add;
t[pos<<1].sum+=(t[pos<<1].r-t[pos<<1].l+1)*t[pos].add;
t[pos<<1|1].add+=t[pos].add;
t[pos<<1|1].sum+=(t[pos<<1|1].r-t[pos<<1|1].l+1)*t[pos].add;
t[pos].add=0;
}
}
ll query(node *t,int l,int r,int pos)
{
if(l<=t[pos].l&&t[pos].r<=r)
{
return t[pos].sum;
}
ll ans=0;
int mid=(t[pos].l+t[pos].r)>>1;
pushdown(t,pos);
if(l<=mid)
ans+=query(t,l,r,pos<<1);
if(r>mid)
ans+=query(t,l,r,pos<<1|1);
return ans;
}
void updata(node *t,int l,int r,int ad,int pos)
{
if(l<=t[pos].l&&t[pos].r<=r)//这里一定要注意是<=和>=
{
t[pos].sum+=(t[pos].r-t[pos].l+1)*ad;
t[pos].add+=ad;
return ;
}
int mid=(t[pos].l+t[pos].r)>>1;
pushdown(t,pos);
if(l<=mid)
updata(t,l,r,ad,pos<<1);//这里是l,r,不是l,mid
if(r>mid)
updata(t,l,r,ad,pos<<1|1);//这里是l,r,不是mid+1,r
t[pos].sum=t[pos<<1].sum+t[pos<<1|1].sum;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(tr,1,n,1);
for(int i=1;i<=q;i++)
{
char c;
//scanf("%c",&c);
cin>>c;
if(c=='Q')
{
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",query(tr,l,r,1));
}
else
{
int l,r,ad;
scanf("%d%d%d",&l,&r,&ad);
updata(tr,l,r,ad,1);
}
}
return 0;
}
题号:zoj-3284
题目大意:就是给你一个矩阵,让你实现一些修改和查询操作
题目思路:建立两个线段树,不细说
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <set> #include <map> #include <stack> #include <vector> #include <queue> #define ri(n) scanf("%d",&n) #define oi(n) printf("%d\n",n) #define rl(n) scanf("%lld",&n) #define ol(n) printf("%lld\n",n) #define rep(i,l,r) for(i=l;i<=r;i++) #define rep1(i,l,r) for(i=l;i<r;i++) using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int epg=10-8; struct node { int l,r; int sum,add; }p[10010<<2],q[10010<<2]; int a[110][110]; void build(node *t,int L,int R,int pos)//建立线段树 { t[pos].l=L; t[pos].r=R; t[pos].sum=0; t[pos].add=0; if(L==R) { return ; } int mid=(L+R)>>1; build(t,L,mid,pos<<1); build(t,mid+1,R,pos<<1|1); } void updown(node *t,int pos)//更新延迟标记,就是相当于分块里面标记整个块,这里标记的是整个区间 { if(t[pos].add!=0) { t[pos<<1].add+=t[pos].add; t[pos<<1|1].add+=t[pos].add; t[pos<<1].sum+=(t[pos<<1].r-t[pos<<1].l+1)*t[pos].add; t[pos<<1|1].sum+=(t[pos<<1|1].r-t[pos<<1|1].l+1)*t[pos].add; t[pos].add=0; } } void upup(node *t,int pos)//回溯求和 { t[pos].sum=t[pos<<1].sum+t[pos<<1|1].sum; } int query(node *t,int x,int pos)//单点查询,查询第x个元素的值 { if(t[pos].l==t[pos].r) { return t[pos].sum; } int mid=(t[pos].l+t[pos].r)>>1; updown(t,pos); if(x<=mid) return query(t,x,pos<<1); //if(R>mid) else return query(t,x,pos<<1|1); } void updata(node *t,int L,int R,int ad,int pos)//区间修改,L-R区间的所有元素加上ad { if(L<=t[pos].l&&t[pos].r<=R) { t[pos].sum+=(t[pos].r-t[pos].l+1)*ad; t[pos].add+=ad; return ; } int mid=(t[pos].l+t[pos].r)>>1; updown(t,pos); if(L<=mid) updata(t,L,R,ad,pos<<1);//这里需要注意一下,容易写错 if(R>mid) updata(t,L,R,ad,pos<<1|1);//这里需要注意一下,容易写错 upup(t,pos); } int main() { int n,m; int kases=0; while(scanf("%d%d",&n,&m)==2) { for(int i=0;i<(10010<<2);i++) { p[i].sum=0;p[i].add=0; q[i].add=0;q[i].sum=0; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); build(p,1,n*m,1); build(q,1,n*m,1); int t; scanf("%d",&t); printf("Case %d\n",++kases); for(int i=1;i<=t;i++) { int x; scanf("%d",&x); if(x==0) { int r1,c1,r2,c2,ad; scanf("%d%d%d%d%d",&r1,&c1,&r2,&c2,&ad); int l=(r1-1)*m+c1,r=(r2-1)*m+c2; updata(p,l,r,ad,1); } else if(x==1) { int r1,c1,r2,c2,ad; scanf("%d%d%d%d%d",&r1,&c1,&r2,&c2,&ad); int l=(c1-1)*n+r1,r=(c2-1)*n+r2; updata(q,l,r,ad,1); } else if(x==2) { int r,c; scanf("%d%d",&r,&c); int ans=query(p,(r-1)*m+c,1)+query(q,(c-1)*n+r,1)+a[r][c]; printf("%d\n",ans); } } } return 0; }
补充:
区间修改区间求求和:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include
bfef
<algorithm>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#define ri(n) scanf("%d",&n)
#define oi(n) printf("%d\n",n)
#define rl(n) scanf("%lld",&n)
#define ol(n) printf("%lld\n",n)
#define rep(i,l,r) for(i=l;i<=r;i++)
#define rep1(i,l,r) for(i=l;i<r;i++)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int epg=10-8;
struct node
{
int l,r;
ll add,sum;
}tr[100010<<2];
ll a[100010<<2];
void build(node *t,int l,int r,int pos)
{
t[pos].l=l;
t[pos].r=r;
t[pos].add=0;
if(l==r)
{
t[pos].sum=a[l];
return;
}
int mid=(t[pos].l+t[pos].r)>>1;
//int mid=(l+r)>>1;
build(t,l,mid,pos<<1);
build(t,mid+1,r,pos<<1|1);
t[pos].sum=t[pos<<1].sum+t[pos<<1|1].sum;
}
void pushdown(node *t,int pos)
{
if(t[pos].add!=0)
{
t[pos<<1].add+=t[pos].add;
t[pos<<1].sum+=(t[pos<<1].r-t[pos<<1].l+1)*t[pos].add;
t[pos<<1|1].add+=t[pos].add;
t[pos<<1|1].sum+=(t[pos<<1|1].r-t[pos<<1|1].l+1)*t[pos].add;
t[pos].add=0;
}
}
ll query(node *t,int l,int r,int pos)
{
if(l<=t[pos].l&&t[pos].r<=r)
{
return t[pos].sum;
}
ll ans=0;
int mid=(t[pos].l+t[pos].r)>>1;
pushdown(t,pos);
if(l<=mid)
ans+=query(t,l,r,pos<<1);
if(r>mid)
ans+=query(t,l,r,pos<<1|1);
return ans;
}
void updata(node *t,int l,int r,int ad,int pos)
{
if(l<=t[pos].l&&t[pos].r<=r)//这里一定要注意是<=和>=
{
t[pos].sum+=(t[pos].r-t[pos].l+1)*ad;
t[pos].add+=ad;
return ;
}
int mid=(t[pos].l+t[pos].r)>>1;
pushdown(t,pos);
if(l<=mid)
updata(t,l,r,ad,pos<<1);//这里是l,r,不是l,mid
if(r>mid)
updata(t,l,r,ad,pos<<1|1);//这里是l,r,不是mid+1,r
t[pos].sum=t[pos<<1].sum+t[pos<<1|1].sum;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(tr,1,n,1);
for(int i=1;i<=q;i++)
{
char c;
//scanf("%c",&c);
cin>>c;
if(c=='Q')
{
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",query(tr,l,r,1));
}
else
{
int l,r,ad;
scanf("%d%d%d",&l,&r,&ad);
updata(tr,l,r,ad,1);
}
}
return 0;
}
相关文章推荐
- HDU 1166 敌兵布阵 <线段树 单点修改 区间查询>
- HDU1166 线段树 单点修改、区间查询
- POJ 3321 Apple Tree(DFS序+线段树单点修改区间查询)
- hdu 5381 The sum of gcd(线段树等差数列区间修改+单点查询)
- BZOJ-1036: [ZJOI2008]树的统计Count (树链剖分 线段树 单点修改 区间查询 入门题)
- 树套树:二维线段树初步:hdu1823——Luck and Love(单点修改,区间查询)
- 1080 线段树练习 单点修改及区间查询
- (HDU 1754)I Hate It 线段树区间查询入门,单点修改
- 考试 线段树二分+单点修改+区间查询
- UVA - 12299 RMQ with Shifts (线段树:单点修改,区间查询)
- 线段树——区间查询+单点修改
- HDU1166_敌兵布阵_线段树单点修改区间查询
- POJ 2155 Matrix 二维线段树 区间修改 单点查询
- 线段树(单点修改,区间查询)
- 【数据结构】【线段树】单点修改区间查询
- hdu 4819 二维线段树,单点修改区间查询
- UVa 12299 RMQ with shifts(线段树单点修改 区间查询)
- poj 3264 Balanced Lineup(线段树单点修改区间查询)
- ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 I.Minimum(线段树_单点修改,查询区间最大最少值)
- hdu 1754 线段树单点修改+区间查询