zoukankan      html  css  js  c++  java
  • SUOI #37 清点更多船只

    经典问题
    正常解法是树状数组或线段树

    但这题内存给的很小
    分块可以省内存

    我们分析一下

    树状数组 线段树 分块
    时间 $NlogN=20 imes 10^6$ $NlogN=20 imes 10^6$ $Nsqrt N=10^3 imes 10^6$
    内存 $2 imes N=2 imes 8 imes 10^6$ $4 imes N=4 imes 24 imes 10^6$ $N+ sqrt N=8024000$

    然后发现都不可行
    怎么办呢?

    其实
    线段树
    没必要开全

    我们可以开到长度为16就不开了
    时间乘10^616
    内存可以做到(1.75 imes N)

    #include <iostream>
    #include <string>
    //#include <fstream>
    
    using namespace std;
    
    //ifstream inf("stp.in", ios_base::in);
    //ofstream outf("stp.out", ios_base::out);
    
    const int MAXN=1111111;
    const int Len=15;
    
    string com;
    int L, R;
    long long op;
    int N, M;
    long long Num[MAXN];
    
    struct Node{
    	int r, l, ls, rs;
    	long long sum, opt;
    } T[MAXN>>3];
    int Tcnt=0;
    
    long long getsum(int l, int r){
    	long long ret=0LL;
    	for(int i=l;i<=r;++i)	ret+=Num[i];
    	return ret;
    }
    
    void getup(int l, int r){
    	for(int i=l;i<=r;++i)	Num[i]+=op;
    }
    
    void pup(int at){
    	if(T[at].r-T[at].l<=Len)	T[at].sum=getsum(T[at].l, T[at].r);
    	else	T[at].sum=T[T[at].ls].sum+T[T[at].rs].sum;
    }
    
    void BuildTree(int l, int r, int at){
    	T[at].l=l;T[at].r=r;T[at].opt=0LL;
    	T[at].ls=-1;T[at].rs=-1;
    	if(r-l>Len){
    		int m=(l+r)>>1;
    		++Tcnt;T[at].ls=Tcnt;
    		BuildTree(l, m, Tcnt);
    		++Tcnt;T[at].rs=Tcnt;
    		BuildTree(m+1, r, Tcnt);
    	}
    	pup(at);
    }
    
    void cop(int at){
    	T[at].opt+=op;
    }
    
    void opr(int at){
    	T[at].sum+=(long long)(T[at].r-T[at].l+1)*op;
    }
    
    void pdw(int at){
    	if(T[at].opt==0LL)	return;
    	int top=op;op=T[at].opt;
    	if(T[at].r-T[at].l<=Len){
    		getup(T[at].l, T[at].r);
    	}
    	else{
    		opr(T[at].ls);cop(T[at].ls);
    		opr(T[at].rs);cop(T[at].rs);
    	}
    	op=top;T[at].opt=0LL;
    }
    
    long long Ask(int at){
    	if(T[at].l>=L && T[at].r<=R){
    		return T[at].sum;
    	}
    	long long ret=0LL;
    	pdw(at);
    	if(T[at].r-T[at].l<=Len){
    		ret=getsum(max(T[at].l, L), min(T[at].r, R));
    //		for(int i=max(T[at].l, L);i<=min(T[at].r, R);++i)
    //			ret+=Num[i];
    	}
    	else{
    		int m=(T[at].l+T[at].r)>>1;
    		if(L<=m)	ret+=Ask(T[at].ls);
    		if(R>m)	ret+=Ask(T[at].rs);
    	}
    	return ret;
    }
    
    void Update(int at){
    	if(T[at].l>=L && T[at].r<=R){
    		opr(at);cop(at);
    		return;
    	}
    	pdw(at);
    	if(T[at].r-T[at].l<=Len){
    		getup(max(T[at].l, L), min(T[at].r, R));
    //		for(int i=max(T[at].l, L);i<=min(T[at].r, R);++i)
    //			Num[i]+=op;
    	}
    	else{
    		int m=(T[at].l+T[at].r)>>1;
    		if(L<=m)	Update(T[at].ls);
    		if(R>m)	Update(T[at].rs);
    	}
    	pup(at);
    }
    
    int main(){
    	ios_base::sync_with_stdio(false);
    	
    	cin >> N >> M;
    	for(int i=1;i<=N;++i)	cin >> Num[i];
    	
    	++Tcnt;
    	BuildTree(1, N, Tcnt);
    	
    	for(int i=1;i<=M;++i){
    		cin >> com;
    		if(com[1]=='s'){
    			cin >> L >> R;
    			cout << Ask(1) << endl;
    		}
    		else{
    			cin >> L >> R >> op;
    			Update(1);
    		}
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    Windows-Windows 下使用 Linux 系统(WSL)
    Windows
    多校3 1002 RGCDQ
    三分 Error Curves
    Equation Again 最大化最小值
    Monthly Expense
    Hamburgers 假定解是否可行
    多校2 1002 Buildings
    UVa 10881 Piotr’s Ants
    多校1 Assignment(枚举 二分 rmq) 1002
  • 原文地址:https://www.cnblogs.com/Pickupwin/p/8613556.html
Copyright © 2011-2022 走看看