pies_0x @ 2024-11-23 13:23:09
是否 sort 一样慢
sort
不 sort
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define N 100005
#define M 100005
int n,m,q;
vector<int> tree[N];
long long v[M],w[N];
int c[N],cnt[N];
int depth[N],fa[N];
int bsize,btot;
int from[N];
int stack[N],top;
struct change{int x,y;}cs[N];int ctot;
struct query{int l,r,times,id;}qs[N];int qtot;
bool flag[N];
long long answer[N];
inline int read()
{
long long x=0,f=1;char c=getchar();
while(c<'0'||c>'9')f=c=='-'?-1:1,c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=getchar();
return x*f;
}
void init(int u)
{
int ftop=top;
for(int v:tree[u])
if(v!=fa[u])
{
depth[v]=depth[u]+1;
fa[v]=u;
init(v);
if(top-ftop>=bsize)
{
++btot;
while(top>ftop)
from[stack[top--]]=btot;
}
}
stack[++top]=u;
}
void add(int type,long long &ans){ans+=v[type]*w[++cnt[type]];}
void del(int type,long long &ans){ans-=v[type]*w[cnt[type]--];}
void chg(int u,long long &ans){if(flag[u])del(c[u],ans),flag[u]=0;else add(c[u],ans),flag[u]=1;}
void modi(change &cg,long long &ans)
{
if(flag[cg.x])
{
del(c[cg.x],ans);
add(cg.y,ans);
}
c[cg.x]^=cg.y;
cg.y^=c[cg.x];
c[cg.x]^=cg.y;
}
signed main()
{
// scanf("%d%d%d",&n,&m,&q);
n=read();m=read();q=read();
for(int i=1;i<=m;++i)
// scanf("%lld",&v[i]);
v[i]=read();
for(int i=1;i<=n;++i)
// scanf("%lld",&w[i]);
w[i]=read();
for(int i=1;i<n;++i)
{
int u,v;
// scanf("%d%d",&u,&v);
u=read();v=read();
tree[u].push_back(v);
tree[v].push_back(u);
}
for(int i=1;i<=n;++i)
// scanf("%d",&c[i]);
c[i]=read();
bsize=pow(n,2.0/3);
init(1);
++btot;
while(top)
from[stack[top--]]=btot;
for(int i=1;i<=q;++i)
{
int op;
// scanf("%d",&op);
op=read();
if(op==0)
// scanf("%d%d",&cs[ctot].x,&cs[++ctot].y);
cs[++ctot].x=read(),cs[ctot].y=read();
else
// scanf("%d%d",&qs[qtot].l,&qs[++qtot].r),
qs[++qtot].l=read(),qs[qtot].r=read(),
qs[qtot].times=ctot,
qs[qtot].id=qtot;
}
sort(qs+1,qs+qtot+1,[](query a,query b){return from[a.l]<from[b.l]||from[a.l]==from[b.l]&&a.times<b.times;}); // 这一行
long long l=1,r=1,times=0,ans=0;
for(int i=1;i<=qtot;++i)
{
int fl=qs[i].l,fr=qs[i].r;
int tl=fl,tr=fr;
chg(fl,ans);
chg(fr,ans);
while(depth[fl]>depth[fr])
fl=fa[fl],
chg(fl,ans);
while(depth[fr]>depth[fl])
fr=fa[fr],
chg(fr,ans);
while(fl!=fr)
fl=fa[fl],
chg(fl,ans),
fr=fa[fr],
chg(fr,ans);
chg(l,ans);
chg(r,ans);
while(depth[l]>depth[r])
l=fa[l],
chg(l,ans);
while(depth[r]>depth[l])
r=fa[r],
chg(r,ans);
while(l!=r)
l=fa[l],
chg(l,ans),
r=fa[r],
chg(r,ans);
while(times<qs[i].times)
modi(cs[++times],ans);
while(times>qs[i].times)
modi(cs[times--],ans);
l=tl;r=tr;
answer[qs[i].id]=ans+v[c[fl]]*w[cnt[c[fl]]+1];
}
for(int i=1;i<=qtot;++i)
printf("%lld\n",answer[i]);
return 0;
}
by renhonglin @ 2024-11-23 13:39:35
分块求和是一种高效的数组处理技巧。
总述: 分块求和通过将大数组分成若干小块,并对每个小块分别求和,最后合并各小块的和来得到整个数组的和,从而加速求和过程。
关键信息:
1、分块策略:根据数组大小和计算机缓存大小等因素,选择合适的块大小。
2、局部求和:对每个小块进行求和,存储结果。
3、合并结果:在需要整体求和时,只需合并各小块的和即可。
这种方法在处理大规模数据时尤为有效,能显著提高求和操作的效率。
by pies_0x @ 2024-11-23 13:40:35
@renhonglin 那我分块哪里错了,蒟蒻看不出来
by renhonglin @ 2024-11-23 13:40:38
https://www.luogu.com.cn/team/90501,你能加一下我的团队吗?
by MLSY_OIer_ZXL @ 2024-11-23 13:44:20
《排名2.29k的蒟蒻》
by renhonglin @ 2024-11-23 13:47:59
@pies_0x 不和样例一样吗???!!!
by pies_0x @ 2024-11-23 13:48:28
@renhonglin 分块分错会T
by renhonglin @ 2024-11-23 13:52:17
what?
by renhonglin @ 2024-11-23 13:53:31
我很垃圾的,你都排名2k了,我才30多k
by XuYueming @ 2024-11-23 21:31:50
@renhonglin ?
by renhonglin @ 2024-11-30 14:47:28
@XuYueming 怎么啦?