树状数组(2025钉耙编程4th 1006进步洛谷3374洛谷3368)
前两题为修改点,查询区间,使用前缀和的思想
洛谷P3374【模板】树状数组 1
P3374 【模板】树状数组 1 - 洛谷
#include<bits/stdc++.h>
#define int long long
using namespace std;
bool tin=0;
int n;
int s[500005];
int lowbit(int x)//查找x低位二次幂数
{
return x&-x;
}
void change(int x,int k)//向后到n修改和
{
while(x<=n) s[x]+=k,x+=lowbit(x);
}
int query(int x)//向前查询和
{
int ans=0;
while(x) ans+=s[x],x-=lowbit(x);
return ans;
}
void solve()
{
int m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
change(i,x);
}
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
if(a==1)
{
change(b,c);
}
else
{
cout<<query(c)-query(b-1)<<'\n';
}
}
}
signed main()
{
std::ios::sync_with_stdio(0) , std::cin.tie(0) , std::cout.tie(0);
int t = 1;
if(tin)
cin >> t ;
while(t--)
solve();
return 0;
}
2025钉耙编程4th 1006 进步
1006 进步
#include<bits/stdc++.h>
#define int long long
using namespace std;
bool tin=1;
int n;
int s[200005],d[200005];
//与板子不同的是修改值,所以要记录原值算出修改量d为原值,s为树状和
int lowbit(int x)//查找x低位二次幂数
{
return x&-x;
}
void change(int x,int k)//向后到n修改和
{
k-=d[x];//与板子不同的是直接更改数值
while(x<=n) s[x]+=k,x+=lowbit(x);
}
int query(int x)//向前查询和
{
int ans=0;
while(x) ans+=s[x],x-=lowbit(x);
return ans;
}
void solve()
{
int m,ans=0,num=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
d[i]=0;//重置数组
change(i,x);
d[i]=x;
}
int a,b,c;
while(m--)
{
cin>>a>>b>>c;
if(a==1)
{
change(b,c);
d[b]=c;
}
else
{
num++;
int t=query(c)/100-query(b-1)/100;//整除100求差
ans^=(t*num);//
}
}
cout<<ans<<'\n';
for(int i=1;i<=n;i++)
s[i]=0;//重置树状数组,最容易犯猪的一集
}
signed main()
{
std::ios::sync_with_stdio(0) , std::cin.tie(0) , std::cout.tie(0);
int t = 1;
if(tin)
cin >> t ;
while(t--)
solve();
return 0;
}
后一题为修改区间而查询点,使用差分的思想
洛谷P3368【模板】树状数组 2
P3368 【模板】树状数组 2 - 洛谷
#include<bits/stdc++.h>
#define int long long
using namespace std;
bool tin=0;
int n;
int s[500005],d[500005];
int lowbit(int x)//查找x低位二次幂数
{
return x&-x;
}
void change(int x,int k)//向后到n修改和
{
while(x<=n) s[x]+=k,x+=lowbit(x);
}
int query(int x)//向前查询和
{
int ans=0;
while(x) ans+=s[x],x-=lowbit(x);
return ans;
}
void solve()
{
int m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>d[i];
}
int x,y,k,op;
while(m--)
{
cin>>op;
if(op==1)
{
cin>>x>>y>>k;
change(x,k),change(y+1,-k);//差分构造
}
else
{
cin>>x;
cout<<d[x]+query(x)<<'\n';//查询前差分并加上原值即为修改后的值
}
}
}
signed main()
{
std::ios::sync_with_stdio(0) , std::cin.tie(0) , std::cout.tie(0);
int t = 1;
if(tin)
cin >> t ;
while(t--)
solve();
return 0;
}