线段树(区间修改,单点查询)
来源:互联网 发布:java 异或运算符 编辑:程序博客网 时间:2024/05/17 04:27
题目链接:https://vjudge.net/contest/196267#problem/B
题号: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 <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;}
阅读全文
0 0
- 线段树(单点修改,区间查询)
- 线段树(区间修改,单点查询)
- 【数据结构】【线段树】单点修改区间查询
- HDU1166 线段树 单点修改、区间查询
- Wikilo 1191线段树区间修改单点查询
- POJ 2155 Matrix 二维线段树 区间修改 单点查询
- hdu 1754 线段树单点修改+区间查询
- hdu 4819 二维线段树,单点修改区间查询
- 考试 线段树二分+单点修改+区间查询
- [模板练习]线段树的单点修改和区间查询
- HDU1166_敌兵布阵_线段树单点修改区间查询
- 线段树——区间查询+单点修改
- 线段树(区间修改,区间查询)
- UVA - 12299 RMQ with Shifts (线段树:单点修改,区间查询)
- poj 3264 Balanced Lineup(线段树单点修改区间查询)
- 树套树:二维线段树初步:hdu1823——Luck and Love(单点修改,区间查询)
- UVa 12299 RMQ with shifts(线段树单点修改 区间查询)
- hdu 5381 The sum of gcd(线段树等差数列区间修改+单点查询)
- TOP100summit:【分享实录-途牛】价格中心系统的优化之路
- Python3 之 Django Web框架优化查询和Form组件(一)
- javascript变量对象
- iframe的应用场景
- 测试基本流程2
- 线段树(区间修改,单点查询)
- OOP思想
- 在centos7服务器上安装anaconda和jupyter notebook
- [arc078f]Mole and Abandoned Mine
- 二叉树的前序,中序,后序遍历Java实现
- retrofit简单的get请求
- spring boot 1.5.7 搭建基础项目框架二 错误: 找不到或无法加载主类
- CSS3去除点input、button击后的出现的边框
- 移植u-boot-2012.04----支持NORFlash启动