• 【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
    ",ans);
    		}
    	}
    	
    	return 0;	
    }
    

      

  • 相关阅读:
    第五周课程总结&实验报告(三)
    第四周Java实验总结&学习总结
    第三周课程总结&实验报告
    第二周JAVA学习总结
    大一学习总结
    寒假第一次作业
    寒假第二次作业
    第十周课程总结
    第九周课程总结&实验报告(七)
    第八周课程总结&实验报告(六)
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/6514781.html
Copyright © 2020-2023  润新知