我两个 log 的做法吊打了一个 log 的做法
查看原帖
我两个 log 的做法吊打了一个 log 的做法
361965
K2Cr2O7楼主2020/10/27 22:16

我真的不敢相信我的代码 这么快

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=500004,SIZE=500002;
char op;
int n,m,x,y,tree[maxn],arr[maxn];

inline void read(int &x){
	char c=getchar();bool f=0;x=0;
	for(;c<'0'||c>'9';c=getchar())
		if(c=='-')
			f=1;
	for(;c>='0'&&c<='9';c=getchar())
		x=x*10+(c^48);
	x=f?-x:x;
}

inline void readc(char &x){
	x=getchar();
	for(;x<'A'||x>'Z';x=getchar());
}

void print(int x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9)
		print(x/10);
	putchar(x%10+48);
}

inline const int lowbit(const int &k){ return k&-k;}
	
int sum(int *a,int p){
	int ans=0;
	while(p){
		ans+=a[p];
		p-=lowbit(p);
	}
	return ans;
}

void add(int *a,int p,int v){
	while(p<=SIZE){
		a[p]+=v;
		p+=lowbit(p);
	}
}

void assign(int *a,int p,int v){//x+m=y,m=y-x;
	add(a,p,v-(sum(a,p)-sum(a,p-1)));
}

int pos(int k){
	int l=1,r=SIZE,ans=0;
	while(l<=r){
		int mid=(l+r)>>1;
		if(sum(tree,mid)>=k){
			r=mid-1;
			ans=mid;
		}
		else
			l=mid+1;
	}
	return ans;
}

signed main(){
	read(n),read(m);
	for(int i=1;i<=n;i++){
		read(x);
		add(arr,i,x);
		add(tree,i,1);
	}
	while(m--){
		readc(op);
		if(op=='C'){
			read(x),read(y);
			add(arr,x,-y);
		}
		else if(op=='I'){
			read(x),read(y);
			assign(tree,x,1);
			assign(arr,x,y);
		}
		else if(op=='D'){
			read(x);
			int p=pos(x);
			add(tree,p,-1);
			assign(arr,p,0);
		}
		else{
			print(sum(arr,SIZE));
			putchar('\n');
		}
	}
	return 0;
} 

各位大佬能分析一下线段树和树状数组的常数吗?谢谢。

2020/10/27 22:16
加载中...