【Codechef-Hard】Chef and Churu 分块

题目链接:

  https://www.codechef.com/problems/FNCS

Solution

大力分块..

对序列分块,维护块内前缀和、块的前缀和,修改时暴力维护两个前缀和,询问单点答案就可以$O(1)$得到。

再对函数分块,维护每块函数的答案、每个位置对每块函数的贡献次数,贡献次数并不会发生改变,修改时只需要暴力修改$\sqrt N$块函数答案。

要开unsigned long long!!!

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
	while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
	return x*f;
}

#define MAXN 100010
#define LL unsigned long long

int N,M,val[MAXN],pl[MAXN],pr[MAXN];

struct Block{
	int l,r,num[MAXN]; LL ans,sum[510];
}b[510];
int belong[MAXN],rk[MAXN],Bn,Bs;
LL Sum[MAXN];

inline void Getsum(int x)
{
	LL t=0;
	for (int i=b[x].l; i<=b[x].r; i++) {
		t+=val[i];
		b[x].sum[rk[i]]=t;
	}
	b[x].sum[Bs]=t;
	for (int i=x; i<=Bn; i++) Sum[i]=Sum[i-1]+b[i].sum[Bs];
}

inline LL Query(int x,int y)
{
	int bx=belong[x],by=belong[y];
	if (bx==by) 
		return b[bx].sum[rk[y]]-b[bx].sum[rk[x]-1];
	else 
		if (bx+1==by)
			return b[by].sum[rk[y]]-b[bx].sum[rk[x]-1]+b[bx].sum[Bs];
		else 
			return b[by].sum[rk[y]]+Sum[by-1]-Sum[bx-1]-b[bx].sum[rk[x]-1];
}

inline void Getnum(int x)
{
	for (int i=b[x].l; i<=b[x].r; i++) {
		b[x].num[pl[i]]++; b[x].num[pr[i]+1]--;
		b[x].ans+=Query(pl[i],pr[i]);
	}
	for (int i=1; i<=N; i++) b[x].num[i]+=b[x].num[i-1];
}

int main()
{
	N=read();
	for (int i=1; i<=N; i++) val[i]=read();
	for (int i=1; i<=N; i++) pl[i]=read(),pr[i]=read();
	
	Bs=int(sqrt(N));
	for (int i=1; i<=N; i++) {
		if ((i-1)%Bs==0) Bn++,b[Bn].l=i;
		belong[i]=Bn; rk[i]=(i-1)%Bs+1;
		if ((i-1)%Bs==Bs-1 || i==N) b[Bn].r=i;
	}
	
	for (int i=1; i<=Bn; i++) Getsum(i);
	for (int i=1; i<=Bn; i++) Getnum(i);
	
	M=read();
	while (M--) {
		int opt=read(),x=read(),y=read(),z;
		if (opt==1) {
			z=y-val[x];
			val[x]=y;
			Getsum(belong[x]);
			for (int i=1; i<=Bn; i++) b[i].ans+=(LL)b[i].num[x]*z;
		} else {
			int bx=belong[x],by=belong[y];
			LL ans=0;
			if (bx==by || bx+1==by)
				for (int i=x; i<=y; i++) ans+=Query(pl[i],pr[i]);
			else {
				for (int i=bx+1; i<=by-1; i++) ans+=b[i].ans;
				for (int i=x; i<b[bx+1].l; i++) ans+=Query(pl[i],pr[i]);
				for (int i=b[by-1].r+1; i<=y; i++) ans+=Query(pl[i],pr[i]);
			}
			printf("%llu\n",ans);
		}
	}
	
	return 0;	
}

  

posted @ 2017-03-07 14:57  DaD3zZ  阅读(444)  评论(0编辑  收藏  举报