您的位置:首页 > 其它

[codechef FNCS]分块处理+树状数组

2017-07-20 00:23 435 查看
题目链接: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: