树状数组的认识与模板
我对树状数组的认识可以参考视频1与视频2,每个人的理解不一样,建议去观看大牛的理解,视频1讲的不太深入,但还是推荐先去看视频1,再去看视频2.
单点修改,区间最大
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=300005;
int h[maxn],a[maxn];
int n,m;
int lowbit(int x)
{
return x&(-x);
}
void update(int x)
{
while(x<=n)
{
h[x]=a[x];
for(int i=1;i<lowbit(x);i<<=1)
h[x]=max(h[x],h[x-i]);
x+=lowbit(x);
}
return ;
}
void findans(int begin,int end)
{
int ans=0;
while(end>=begin)
{
ans=max(ans,a[end]);
end--;
for(;end-lowbit(end)>=begin;end-=lowbit(end))
ans=max(ans,h[end]);
}
printf("%d\n",ans);
return ;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(scanf("%d%d",&n,&m)==2)
{
memset(h,0,sizeof(h));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
update(i);
}
for(int i=1;i<=m;i++)
{
char c=getchar();
while(c!='Q'&&c!='U')c=getchar();
if(c=='U')//update
{
int y,z;
scanf("%d%d",&y,&z);
a[y]=z;
update(y);
continue;
}
if(c=='Q')//findans
{
int y,z;
scanf("%d%d",&y,&z);
findans(y,z);
continue;
}
}
}
return 0;
}
hdu1166(单点修改区间求和)
#include<bits/stdc++.h>
#define maxn 111111
using namespace std;
int n;
int c[maxn];
int b[maxn];
int lowbit(int x) {
return x&-x;
}
/**单点修改区间求和**/
/**
add(x,num);
sum(r)-sum(l-1);
每次x号位置修改num
求lr闭区间的和
**/
void add(int k,int num) {
while(k<=n) {
c[k]+=num;
k+=lowbit(k);
}
}
int sum(int k) {
int ans=0;
while(k) {
ans+=c[k];
k-=lowbit(k);
}
return ans;
}
int main()
{
int t;
int kase=0;
scanf("%d",&t);
while(t--) {
memset(c,0,sizeof c);
printf("Case %d:\n",++kase);
scanf("%d",&n);
int x,y;
for(int i=1;i<=n;i++) {
scanf("%d",&x);
add(i,x);
}
char s[10];
while(scanf("%s",s)&&strcmp(s,"End")!=0) {
if(strcmp(s,"Query")==0) {
scanf("%d%d",&x,&y);
printf("%d\n",sum(y)-sum(x-1));
}
else {
if(strcmp(s,"Add")==0) {
scanf("%d%d",&x,&y);
add(x,y);
}
else {
scanf("%d%d",&x,&y);
add(x,-y);
}
}
}
}
return 0;
}
hdu 1556(区间修改单点求值)
#include<bits/stdc++.h>
#define maxn 111111
using namespace std;
int n;
int c[maxn];
int b[maxn];
int lowbit(int x) {
return x&-x;
}
/**区间修改单点询问**/
/**
add(l-1,-num);add(r,num);
sum(x);
每次修改闭区间lr的值,询问x节点的值
**/
void add(int k,int num) {
while(k) {
b[k]+=num;
k-=lowbit(k);
}
}
int sum(int k) {
int ans=0;
while(k<=n) {
ans+=b[k];
k+=lowbit(k);
}
return ans;
}
int main()
{
while(scanf("%d",&n)&&(n!=0)) {
memset(b,0,sizeof b);
int x,y;
for(int i=1;i<=n;i++) {
scanf("%d%d",&x,&y);
add(x-1,-1);
add(y,1);
}
for(int i=1;i<n;i++) {
printf("%d ",sum(i));
}
printf("%d\n",sum(n));
}
return 0;
}
给出一个全0的矩阵,然后一些操作
0 S:初始化矩阵,维数是S*S,值全为0,这个操作只有最开始出现一次
1 X Y A:对于矩阵的X,Y坐标增加A
2 L B R T:询问(L,B)到(R,T)区间内值的总和
3:结束对这个矩阵的操作
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define MEM(a,x) memset(a,x,sizeof(a))
#define LL long long
#define N 2005
#define INF 0x3f3f3f3f
#define lowbit(x) (x&-x)
const int mod = 1e9+7;
int a[N];
int n,c[N][N],ans[N],x,y;
int sum(int x,int y)
{
int ret=0,i,j;
for(i = x; i>0; i-=lowbit(i))
{
for(j = y; j>0; j-=lowbit(j))
{
ret+=c[i][j];
}
}
return ret;
}
void add(int x,int y,int d)
{
int i,j;
for(i = x; i<=n; i+=lowbit(i))
{
for(j = y; j<=n; j+=lowbit(j))
{
c[i][j]+=d;
}
}
}
int main()
{
int i,j,k,op,x,y;
while(~scanf("%d%d",&i,&n))
{
MEM(c,0);
while(1)
{
scanf("%d",&op);
if(op==3)
break;
if(op==1)
{
scanf("%d%d%d",&x,&y,&k);
add(x+1,y+1,k);
}
else
{
int l,b,r,t;
scanf("%d%d%d%d",&l,&b,&r,&t);
l++,b++,r++,t++;
printf("%d\n",sum(r,t)-sum(r,b-1)-sum(l-1,t)+sum(l-1,b-1));
}
}
}
return 0;
}
题目描述 Description
给你N个数,有两种操作:
1:给区间[a,b]的所有数增加X
2:询问区间[a,b]的数的和。
输入描述 Input Description
第一行一个正整数n,接下来n行n个整数,
再接下来一个正整数Q,每行表示操作的个数,
如果第一个数是1,后接3个正整数,
表示在区间[a,b]内每个数增加X,如果是2,
表示操作2询问区间[a,b]的和是多少。
pascal选手请不要使用readln读入
输出描述 Output Description
对于每个询问输出一行一个答案
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<set>
const int MAXN=200000*4;
using namespace std;
int lowbit(int x){return x&(-x);}
int n,Q,opt,x,y;
long long A[MAXN],C[MAXN],sum[MAXN],z;
void modifyA(int x,int val){
while(x<=n){
A[x]+=val;
x+=lowbit(x);
}
}
void modifyC(int x,long long val){
while(x<=n){
C[x]+=val;
x+=lowbit(x);
}
}
void update(int from,int to,long long val){
modifyA(from,val);
modifyA(to+1,-val);
modifyC(from,val*from);
modifyC(to+1,-val*(to+1));
}
long long queryA(int loc){
long long ans=0;
while(loc){
ans+=A[loc];
loc-=lowbit(loc);
}
return ans;
}
long long queryC(int loc){
long long ans=0;
while(loc){
ans+=C[loc];
loc-=lowbit(loc);
}
return ans;
}
long long query(int loc){
return sum[loc]+(loc+1)*queryA(loc)-queryC(loc);
}
long long query(int from,int to){
return query(to)-query(from-1);
}
int main(){
scanf("%d",&n);
for(register int i=1;i<=n;i++)scanf("%d",&sum[i]),sum[i]+=sum[i-1];
scanf("%d",&Q);
while(Q--){
scanf("%d%d%d",&opt,&x,&y);
if(opt==1){
scanf("%lld",&z);
update(x,y,z);
}else{
printf("%lld\n",query(x,y));
}
}
return 0;
}