[codechef FNCS]分块处理+树状数组
Posted ACMsong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[codechef FNCS]分块处理+树状数组相关的知识,希望对你有一定的参考价值。
题目链接:https://vjudge.net/problem/CodeChef-FNCS
在一个地方卡了一晚上,就是我本来以为用根号n分组,就会分成根号n个。事实上并不是。。。。因为用的是根号n下取整分组,得到的组数要用n/floor(sqrt(n))具体计算。
另外还有各种奇怪的bug……包括unsigned long long什么的……orz
#include<bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int maxn=100005; int a[maxn]; int fl[maxn],fr[maxn]; int cnt[maxn][320]; ull res[320]; ull tree[maxn]; int N,block_size; int lowbit(int x) { return x&-x; } void add(int k,int x) { while (k<=N) { tree[k]+=x; k+=lowbit(k); } } ull query(int k) { ull res=0ull; while (k) { res+=tree[k]; k-=lowbit(k); } return res; } void init(int n) { N=n; for (int i=1;i<=N;i++) tree[i]=0ull; } ull query2(int k) { if (k<1) return 0; ull r=0ull; int block_id=(k-1)/block_size+1; for (int i=1;i<block_id;i++) r+=res[i]; for (int i=(block_id-1)*block_size+1;i<=k;i++) { r+=query(fr[i])-query(fl[i]-1); } return r; } int main() { int n; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=n;i++) scanf("%d%d",&fl[i],&fr[i]); block_size=sqrt(n); int block=n/block_size; for (int i=1;i<=block;i++) { for (int j=(i-1)*block_size+1;j<=i*block_size;j++) { cnt[fr[j]+1][i]--; cnt[fl[j]][i]++; } res[i]=0; for (int j=1;j<=n;j++) { cnt[j][i]+=cnt[j-1][i]; res[i]+=1ull*a[j]*cnt[j][i]; } } init(n); for (int i=1;i<=n;i++) add(i,a[i]); int q; scanf("%d",&q); while (q--) { int op,x,y; scanf("%d%d%d",&op,&x,&y); if (op==2) { ull r=query2(y)-query2(x-1); printf("%llu\n",r); } else { for (int i=1;i<=block;i++) { res[i]+=1ull*cnt[x][i]*(y-a[x]); } add(x,y-a[x]); a[x]=y; } } return 0; }
以上是关于[codechef FNCS]分块处理+树状数组的主要内容,如果未能解决你的问题,请参考以下文章