• [Ynoi2012]D1T1


    题目

    套路的根号分治啊

    我们设置一个值(S)

    对于(Sleq x)的操作,我们直接暴力修改,显然这样只会修改(frac{n}{S})次,所以我们需要一个能够(O(1))修改的数据结构,自然是首选分块

    对于(S>x)的操作,我们对于每一个(x)维护一个块,我们维护这个块的前缀和就好了,复杂度是(O(S))

    查询的时候先用分块查一下区间和,复杂度(O(S+frac{n}{S})),之后对于每一个(x<S)的块我们单独(O(1))求一下,复杂度是(O(S))

    理论上自然是(S=sqrt{n})的时候取到了最优的复杂度,但是我们根据一些奇怪的常数原因,可以魔改一波块大小

    代码

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define re register
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int maxn=2e5+5;
    const int mod=1e9+7;
    int n,m,sz;
    int pr[500][500],sum[500];
    int pre[maxn],id[maxn],l[5000];
    inline int qm(int a) {return a>=mod?a-mod:a;}
    struct Block {
    	int a[maxn],tag[5000];
    	inline void change(int pos,int v) {
    		a[pos]=qm(a[pos]+v);
    		tag[id[pos]]=qm(tag[id[pos]]+v);
    	}
    	inline int ask(int x) {
    		int now=0;
    		for(re int i=1;i<id[x];i++) now=qm(now+tag[i]);
    		for(re int i=l[id[x]];i<=x;i++) now=qm(now+a[i]);
    		return now;
    		
    	}
    }B;
    inline int find(int x,int y) {return !(y%x)?y/x:y/x+1;}
    inline int solve(int x,int y) {
    	if(!y) return 0;
    	return qm(1ll*(find(x,y)-1)*sum[x]%mod+pr[x][(y%x)?y%x:x]);
    }
    int main() {
    	n=read(),m=read();
    	for(re int i=1;i<=n;i++) pre[i]=(pre[i-1]+read())%mod;
    	sz=std::sqrt(n);int L=1,tot=0;sz=250;
    	while(L<=n) {
    		l[++tot]=L;
    		for(re int i=L;i<=min(L+sz-1,n);i++) id[i]=tot;
    		L+=sz;
    	}
    	int op,x,y,v;
    	while(m--) {
    		op=read(),x=read(),y=read();
    		if(op==2) {
    			int ans=(pre[y]-pre[x-1]+mod)%mod;
    			ans=(ans+B.ask(y)-B.ask(x-1))%mod;
    			for(re int i=1;i<sz;i++) ans=(ans+solve(i,y)-solve(i,x-1))%mod;
    			printf("%d
    ",(ans+mod)%mod);
    		}
    		if(op==1) {
    			v=read();
    			if(x>=sz) {while(y<=n) B.change(y,v),y+=x;continue;}
    			sum[x]=(sum[x]+v)%mod;
    			for(re int i=y;i<=x;i++) pr[x][i]=qm(pr[x][i]+v);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    软件工程-案例分析作业 开源代码托管平台
    软件工程-个人阅读作业 #2
    软件工程-个人阅读作业 #1
    提问回顾与个人总结
    软工案例分析作业
    结对编程——第二阶段
    软工个人阅读作业#2
    软工个人阅读作业#1
    OO补给站总结
    BUAA_2021_SE_Final_Report
  • 原文地址:https://www.cnblogs.com/asuldb/p/10853505.html
Copyright © 2020-2023  润新知