codeforces 915E - Physical Education Lessons 动态开点线段树

题意:

最大$10^9$的区间,

$3*10^5$次区间修改,每次操作后求整个区间的和

题解:

裸的动态开点线段树,计算清楚数据范围是关键...

经过尝试

$2*10^7$会$MLE$

$10^7$会$RE$

用$vector$但是一开始没有$resize$到最大也会$MLE$

如果节点内部信息保存了节点的区间,无论怎么样都会$MLE$

最终$1.5*10^7$的$vector$/数组可以过

#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
using namespace std;
int casn,n,m,k;
const int maxn=1e7+5e6+7;
class dsegtree{public:
#define nd  node[now]
#define ndl node[node[now].son[0]]
#define ndr node[node[now].son[1]]
    struct dsegnode {
        int son[2],tag,sum;
        dsegnode(){}
        dsegnode(int s,int t){sum=t-s+1,tag=son[0]=son[1]=0;}
        void update(int x,int len){sum=len*(x-1),tag=x;}
    };
    vector<dsegnode> node;
	int root,cnt,n,s,t;
    dsegtree(int nn,int size=maxn){
    	n=nn;
    	node.resize(maxn);
    	node[1]=dsegnode(1,n);
    	cnt=root=1;
	}
    void pushup(int now){nd.sum=ndl.sum+ndr.sum;}
    void pushdown(int now,int s,int t){
		if(nd.tag){
			ndl.update(nd.tag,(t+s)/2-s+1);
			ndr.update(nd.tag,t-((t+s)/2+1)+1);
			nd.tag=0;
		}
    }
    void update(int ss,int tt,int x){s=ss,t=tt,update(1,n,x,root);}
    void update(int l,int r,int x,int now){
    	if(s>r||t<l)return ;
    	if(s<=l&&t>=r) {
			nd.update(x,r-l+1);
			return ;
    	}
    	if(!nd.son[0]){
			node[++cnt]=dsegnode(l,(l+r)>>1);
			nd.son[0]=cnt;
    	}
    	if(!nd.son[1]){
			node[++cnt]=dsegnode(((l+r)>>1)+1,r);
			nd.son[1]=cnt;
    	}
    	pushdown(now,l,r);
		update(l,(l+r)>>1,x,nd.son[0]);
		update(((l+r)>>1)+1,r,x,nd.son[1]);
    	pushup(now);
    }
};

int main() {
	IO;
	ll n,m;
	cin>>n>>m;
	dsegtree tree(n);
	int a,b,c;
	while(m--){
		cin>>a>>b>>c;
		tree.update(a,b,c);
		cout<<tree.node[tree.root].sum<<endl;
	}
	return 0;
}

 

 

91

题解5

posted @ 2019-01-07 15:44  nervending  阅读(312)  评论(0编辑  收藏  举报