• Chtholly_tree


    神仙数据结构 Chtholly_tree(ODT)

    我永远喜欢珂朵莉

    Chtholly_tree简介

    这是一种很暴力的数据结构(只是暴力,但不黄),基于( exttt{STLset})
    主要用于骗分,可以很好地适应随机数据。
    有时可以碾压分块和线段树。

    代码集合

    #include<set>
    #include<vector>
    #include<cstdio>
    #include<utility>
    #include<algorithm>
    
    #define ODT Chtholly_tree
    
    #define LL long long
    
    using namespace std;
    
    struct Chtholly_tree {
    	int ll,rr;
    	mutable LL val;
    	Chtholly_tree(int L,int R=-1,LL V=0): ll(L), rr(R), val(V) {}
    	bool operator < (const Chtholly_tree& tt)const {
    		return ll<tt.ll;
    	}
    };
    
    set<ODT> odt;
    set<ODT>::iterator split(int pos) {
    	set<ODT>::iterator it=odt.lower_bound(ODT(pos));
    	if (it!=odt.end()&&it->ll==pos) return it;
    	--it;
    	ODT tmp=*it;
    	odt.erase(it);
    	odt.insert(ODT(tmp.ll,pos-1,tmp.val));
    	return odt.insert(ODT(pos, tmp.rr, tmp.val)).first;
    }
    void assign(int l,int r,LL val) {
    	set<ODT>::iterator itr=split(r+1), itl=split(l);
    	odt.erase(itl,itr);
    	odt.insert(ODT(l,r,val));
    }
    void add(int l,int r,LL val) {
    	set<ODT>::iterator itr=split(r+1),itl=split(l);
    	for(set<ODT>::iterator it=itl; it!=itr; it++) it->val+=val;
    }
    LL sum(int l, int r) {
    	set<ODT>::iterator itr=split(r + 1),itl=split(l);
    	LL res=0;
    	for(set<ODT>::iterator it=itl; it!=itr;it++) res+=(it->rr-it->ll+1)*it->val;
    	return res;
    }
    LL rank(int l, int r, int k){
        vector<pair<LL, int> >vec(0);
        set<ODT>::iterator itr=split(r+1),itl=split(l);
        for(set<ODT>::iterator it=itl;it!=itr;it++)vec.push_back(make_pair(it->val,it->rr-it->ll+1));
        sort(vec.begin(),vec.end());
        for (vector<pair<LL,int> >::iterator it=vec.begin();it!=vec.end();it++) if((k-=it->second)<=0) return it->first;
        return -1; //note:if there are negative numbers, return another impossible number.
    }
    int main() {
    }
    
    

    例题:

    CF896C Willem, Chtholly and Seniorious
    CF915E Physical Education Lessons
    P2787 语文1(chin1)- 理理思维

    标程:

    CF915E

    //by     G_M_H      2019 11 12
    //优化常数,将sum加到assign中,组成assign_new
    #include<set>
    #include<vector>
    #include<cstdio>
    #include<utility>
    #include<algorithm>
    
    #define ODT Chtholly_tree
    
    #define LL long long
    
    using namespace std;
    
    struct Chtholly_tree {
    	int ll,rr;
    	mutable LL val;
    	Chtholly_tree(int L,int R=-1,LL V=0): ll(L), rr(R), val(V) {}
    	bool operator < (const Chtholly_tree& tt)const {
    		return ll<tt.ll;
    	}
    };
    
    set<ODT> odt;
    LL ans=0;
    set<ODT>::iterator split(int pos) {
    	set<ODT>::iterator it=odt.lower_bound(ODT(pos));
    	if (it!=odt.end()&&it->ll==pos) return it;
    	--it;
    	ODT tmp=*it;
    	odt.erase(it);
    	odt.insert(ODT(tmp.ll,pos-1,tmp.val));
    	return odt.insert(ODT(pos, tmp.rr, tmp.val)).first;
    }
    void assign(int l,int r,LL val) {
    	set<ODT>::iterator itr=split(r+1), itl=split(l);
    	odt.erase(itl,itr);
    	odt.insert(ODT(l,r,val));
    }
    void assign_new(int l,int r,LL val) {
    	set<ODT>::iterator itr=split(r+1), itl=split(l);
    	for(set<ODT>::iterator it=itl;it!=itr;it++) ans-=it->val*(it->rr-it->ll+1);
    	odt.erase(itl,itr);
    	odt.insert(ODT(l,r,val));
    	ans+=val*(r-l+1);
    }
    void add(int l,int r,LL val) {
    	set<ODT>::iterator itr=split(r+1),itl=split(l);
    	for(set<ODT>::iterator it=itl; it!=itr; it++) it->val+=val;
    }
    LL sum(int l,int r) {
    	set<ODT>::iterator itr=split(r+1),itl=split(l);
    	LL res=0;
    	for(set<ODT>::iterator it=itl; it!=itr;it++) res+=(it->rr-it->ll+1)*it->val;
    	return res;
    }
    LL rank(int l, int r, int k){
        vector<pair<LL, int> >vec(0);
        set<ODT>::iterator itr=split(r+1),itl=split(l);
        for(set<ODT>::iterator it=itl;it!=itr;it++)vec.push_back(make_pair(it->val,it->rr-it->ll+1));
        sort(vec.begin(),vec.end());
        for (vector<pair<LL,int> >::iterator it=vec.begin();it!=vec.end();it++) if((k-=it->second)<=0) return it->first;
        return -1; //note:if there are negative numbers, return another impossible number.
    }
    int n,m,l,r,op;
    int main() {
    	scanf("%d%d",&n,&m);
    	odt.insert(ODT(1,n,1));
    	ans=n;
    	while(m--) {
    		scanf("%d%d%d",&l,&r,&op);
    		if(op==1) assign_new(l,r,0);
    		else assign_new(l,r,1);
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    【HDU3480】Division-DP+四边形不等式优化+贪心
    【HDU3480】Division-DP+四边形不等式优化+贪心
    【NOI2015T2】软件包管理器-树链剖分维护路径和子树信息
    【NOI2015T2】软件包管理器-树链剖分维护路径和子树信息
    【APIO2011T1】方格染色-并查集+位运算推导
    【APIO2011T1】方格染色-并查集+位运算推导
    【NOI2016T4】区间-线段树+离散化+决策单调性优化
    【NOI2016T4】区间-线段树+离散化+决策单调性优化
    【NOI2010T4】航空管制-拓补排序+贪心
    BZOJ 1753 Who's in the Middle
  • 原文地址:https://www.cnblogs.com/STOGMH/p/11844736.html
Copyright © 2020-2023  润新知