这就是道打暴力题 不过我偷懒写的复杂度较高
考虑把
sumi
分成m块 然后我们预处理出每个点对每块的贡献
就可以
O(m)
处理修改操作
然后询问 如果我们用树状数组维护子树和 我们可以做到
O(m+nmlogn)
我们取
m=nlogn−−−−−√
复杂度就是
O(nnlogn−−−−−√)
竟然被我跑过了
其实把树状数组改成分块 加上差分 然后就可以
O(n√)
修改
O(1)
询问 那么就是
O(nn√)
的复杂度啦 Hillan orz
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef unsigned long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline void write(ll x) {
if (!x) return (void) printf("0 ");
static short s[25], t;
while (x) s[++t] = x % 10, x /= 10;
while (t) putchar('0' + s[t--]);
putchar('\n');
}
const int N=100005;
ll c[N]; int maxn;
inline void init(int n){
maxn=n; for (int i=1;i<=n;i++) c[i]=0;
}
inline void add(int x,int r){
for (int i=x;i<=maxn;i+=i&-i)
c[i]+=r;
}
inline ll sum(int x){
ll ret=0;
for (int i=x;i;i-=i&-i)
ret+=c[i];
return ret;
}
inline ll sum(int l,int r){
return sum(r)-sum(l-1);
}
struct edge{
int u,v,next;
}G[N<<1];
int head[N],inum;
inline void add(int u,int v,int p){
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
#define V G[p].v
int rt,val[N];
int pre[N],clk;
int size[N];
inline void dfs(int u,int fa){
pre[u]=++clk; size[u]=1;
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
dfs(V,u),size[u]+=size[V];
}
inline ll Sum(int u){
return sum(pre[u],pre[u]+size[u]-1);
}
const int B=1002;
int pos[N];
int Blo,tot,lp[B],rp[B];
short cnt[B][N];
ll Ans[B];
inline void Query(int l,int r){
int lb=pos[l],rb=pos[r];
ll ret=0;
if (lb==rb){
for (int i=l;i<=r;i++)
ret+=Sum(i);
write(ret);
//printf("%llu\n",ret);
return;
}
for (int i=lb+1;i<rb;i++) ret+=Ans[i];
for (int i=l;i<=rp[lb];i++)
ret+=Sum(i);
for (int i=lp[rb];i<=r;i++)
ret+=Sum(i);
write(ret);
//printf("%llu\n",ret);
}
int n;
short tmp[N];
int main(){
int order,iu,iv,Q;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(Q); init(n);
for (int i=1;i<=n;i++) read(val[i]);
for (int i=1;i<=n;i++){
read(iu),read(iv);
if (!iu) rt=iv;
else if (!iv) rt=iu;
else add(iu,iv,++inum),add(iv,iu,++inum);
}
dfs(rt,0);
for (int i=1;i<=n;i++) add(pre[i],val[i]);
Blo=min((int)sqrt((double)n*log(n)/log(2)),1000);
for (int i=1;i<=n;i++) pos[i]=(i-1)/Blo+1;
tot=pos[n];
for (int i=1;i<=tot;i++) lp[i]=Blo*(i-1)+1,rp[i]=Blo*i;
rp[tot]=n;
for (int i=1;i<=tot;i++){
memset(tmp+1,0,sizeof(short)*n);
for (int j=lp[i];j<=rp[i];j++)
Ans[i]+=Sum(j),tmp[pre[j]]++,tmp[pre[j]+size[j]]--;
for (int j=1;j<=n;j++)
cnt[i][j]=(tmp[j]+=tmp[j-1]);
}
while (Q--){
read(order); read(iu); read(iv);
if (order==1){
for (int i=1;i<=tot;i++)
Ans[i]+=(ll)(iv-val[iu])*cnt[i][pre[iu]];
add(pre[iu],iv-val[iu]);
val[iu]=iv;
}else{
Query(iu,iv);
}
}
return 0;
}