目录
单点修改
import java.io.*;
import java.math.BigInteger;
import java.util.Scanner;
/**
* @Author DragonOne
* @Date 2021/12/5 21:27
* @墨水记忆 www.tothefor.com
*/
public class Main {
public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
public static Scanner sc = new Scanner(System.in);
public static int maxd = 100000+7;
public static int[] a = new int[maxd]; //原数组
public static int[] tree = new int[maxd*4]; //树存储
//初始化建树
public static void build(int p,int l,int r){
if(l==r){
tree[p]=a[l];
return ;
}
int mid = (r+l)/2; // 防止爆范围
build(p*2,l,mid); //左子树
build(p*2+1,mid+1,r); //右子树
tree[p]=tree[p*2]+tree[p*2+1];
}
//将x位置的值加上num
public static void update(int p,int l,int r,int x,int num){
if(x>r||x<l) return ;
if(l==r&&l==x){ //找到x位置
tree[p] += num; //灵活变
return ;
}
int mid = (r+l)/2;
update(p*2,l,mid,x,num);
update(p*2+1,mid+1,r,x,num);
tree[p]=tree[p*2]+tree[p*2+1];
}
//查询区间和
public static int query(int p,int l, int r ,int x, int y){
if(x<=l&&r<=y) return tree[p];
if(x>r||y<l) return 0;
int mid = (r+l)/2;
int sum = 0;
sum+=query(p*2,l,mid,x,y);
sum+=query(p*2+1,mid+1,r,x,y);
return sum;
}
public static void main(String[] args) throws Exception {
int n = nextInt();
int m = nextInt();
for(int i=1;i<=n;++i){
a[i] = nextInt();
}
build(1,1,n); //注意此位置必须在a数组输入后
for(int i=1;i<=m;++i){
int a1 = nextInt();
int a2 = nextInt();
int a3 = nextInt();
if(a1==1) update(1,1,n,a2,a3);
else System.out.println(query(1,1,n,a2,a3));
}
closeAll();
}
public static void cinInit(){
cin.wordChars('a', 'z');
cin.wordChars('A', 'Z');
cin.wordChars(128 + 32, 255);
cin.whitespaceChars(0, ' ');
cin.commentChar('/');
cin.quoteChar('"');
cin.quoteChar('\'');
cin.parseNumbers(); //可单独使用来还原数字
}
public static int nextInt() throws Exception{
cin.nextToken();
return (int) cin.nval;
}
public static long nextLong() throws Exception{
cin.nextToken();
return (long) cin.nval;
}
public static double nextDouble() throws Exception{
cin.nextToken();
return cin.nval;
}
public static String nextString() throws Exception{
cin.nextToken();
return cin.sval;
}
public static void closeAll() throws Exception {
cout.close();
in.close();
out.close();
}
}
测试数据:
10 2
1 2 3 4 5 6 7 8 9 10
1 1 9
2 1 10
结果
64
区间修改
import java.io.*;
import java.math.BigInteger;
import java.util.Scanner;
/**
* @Author DragonOne
* @Date 2021/12/5 21:27
* @墨水记忆 www.tothefor.com
*/
public class Main {
public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
public static Scanner sc = new Scanner(System.in);
public static int maxd = 100000+7;
public static int[] a = new int[maxd]; //原数组
public static int[] tree = new int[maxd*4]; //树存储
public static int[] lazy = new int[maxd*4]; //懒惰标记
//初始化建树
public static void build(int p,int l,int r){
if(l==r){
tree[p]=a[l];
return ;
}
int mid = (r+l)/2; // 防止爆范围
build(p*2,l,mid); //左子树
build(p*2+1,mid+1,r); //右子树
tree[p]=tree[p*2]+tree[p*2+1];
lazy[p]=0;
}
public static void push_down(int p ,int l ,int r ){
if(lazy[p]!=0){
lazy[p*2] += lazy[p];
lazy[p*2+1] += lazy[p];
int mid = (r+l)/2;
tree[p*2] += (mid-l+1) * lazy[p];
tree[p*2+1] += (r-mid) * lazy[p];
lazy[p]=0;
}
}
//将区间(x,y)的值加上num
public static void update(int p,int l,int r,int x,int y,int num){
if(x>r||x<l) return ;
if(x<=l&&r<=y){ //找到区间
lazy[p] += num;
tree[p] += (r-l+1)*num;
return ;
}
push_down(p,l,r);
int mid = (r+l)/2;
update(p*2,l,mid,x,y,num);
update(p*2+1,mid+1,r,x,y,num);
tree[p]=tree[p*2]+tree[p*2+1];
}
//查询区间和
public static int query(int p,int l, int r ,int x, int y){
if(x<=l&&r<=y) return tree[p];
if(x>r||y<l) return 0;
push_down(p,l,r);
int mid = (r+l)/2;
int sum = 0;
sum+=query(p*2,l,mid,x,y);
sum+=query(p*2+1,mid+1,r,x,y);
// tree[p]=tree[p*2]+tree[p*2+1];
return sum;
}
public static void main(String[] args) throws Exception {
int n = nextInt();
int m = nextInt();
for(int i=1;i<=n;++i) a[i] = nextInt();
build(1,1,n);
for(int i=1;i<=m;++i){
int a1 = nextInt();
if(a1==1) {
int a2 = nextInt();
int a3 = nextInt();
System.out.println(query(1,1,n,a2,a3));
}
else {
int a2 = nextInt();
int a3 = nextInt();
int a4 = nextInt();
update(1,1,n,a2,a3,a4);
}
}
closeAll();
}
public static void cinInit(){
cin.wordChars('a', 'z');
cin.wordChars('A', 'Z');
cin.wordChars(128 + 32, 255);
cin.whitespaceChars(0, ' ');
cin.commentChar('/');
cin.quoteChar('"');
cin.quoteChar('\'');
cin.parseNumbers(); //可单独使用来还原数字
}
public static int nextInt() throws Exception{
cin.nextToken();
return (int) cin.nval;
}
public static long nextLong() throws Exception{
cin.nextToken();
return (long) cin.nval;
}
public static double nextDouble() throws Exception{
cin.nextToken();
return cin.nval;
}
public static String nextString() throws Exception{
cin.nextToken();
return cin.sval;
}
public static void closeAll() throws Exception {
cout.close();
in.close();
out.close();
}
}
测试数据:
5 3
1 2 3 4 5
1 1 5
2 1 5 -1
1 1 5
输出:
15
10
还有二维线段树。有机会再写吧。