[NOIP school training] multiset (dynamic prescription segment tree / + segment tree balanced tree)

The meaning of problems

N-squares \ ((n \ Leq 1E5) \) , each grid initial weight value of zero. It supports two operations: 1. Each time the \ ([l, r] \ ) in all the grid was added an item i, for a grid, if it is first added to i, the weight value by 1, otherwise the weights Total times;. 2 summation interval
article with the kind and order n

Thinking

While taking into account the many categories of items, but the number is still operating range 1e5 level, so you can use a dynamic data structure to maintain

1.set + segment tree

Exam practice

The first idea is as much open brainless number and type of set, each set intervals to maintain all one color, so the question becomes quickly find the range to be added and some have overlapping partial sections will overlapped portion by 2, adding 1 to the rest.

Similarly venue reservation , all of the overlapping sections can be found directly with the find operation to modify the operation, we will then delete them, and the interval to be added toMerge, Was then added as a block section to join them set. Because a section be traversed once will be deleted, so the time complexity of the algorithm is \ (O (nlog ^ 2n) \)

Code

#include<bits/stdc++.h>
#define N 200005
#define Min(x,y) ((x)<(y)?(x):(y))
#define Max(x,y) ((x)>(y)?(x):(y))
#define IT set<SXK>::iterator
using namespace std;
typedef long long ll;
const ll mod = 998244353;
int n,q;
ll sum[N<<2],sign_mul[N<<2],sign_add[N<<2];
struct SXK
{
    int l,r;
    SXK(int ll=0,int rr=0) {l=ll;r=rr;}
    bool operator < (const SXK a)const
    {
        return r < a.l;
    }
};//保证同颜色的区间不重叠 
set<SXK> col[N];

template <class T>
void read(T &x)
{
    char c;int sign=1;
    while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}

void add_sign_add(int rt,int l,int r,ll val)
{
    sign_add[rt]=(sign_add[rt]+val)%mod;
    sum[rt]=(sum[rt]+(r-l+1)*val%mod)%mod;
}
void add_sign_mul(int rt,int l,int r,ll val)
{
    sign_add[rt]=sign_add[rt]*val%mod;
    sign_mul[rt]=sign_mul[rt]*val%mod;
    sum[rt]=sum[rt]*val%mod;
}
void pushdown(int rt,int l,int r)
{
    if(sign_mul[rt]==1&&sign_add[rt]==0) return;
    int mid=(l+r)>>1;
    add_sign_mul(rt<<1,l,mid,sign_mul[rt]); 
    add_sign_add(rt<<1,l,mid,sign_add[rt]);
    add_sign_mul(rt<<1|1,mid+1,r,sign_mul[rt]);
    add_sign_add(rt<<1|1,mid+1,r,sign_add[rt]); 
    sign_mul[rt]=1;
    sign_add[rt]=0;
}
void modify_add(int rt,int l,int r,int x,int y)
{
    if(x>y) return;
    if(x<=l&&r<=y) return add_sign_add(rt,l,r,1);
    int mid=(l+r)>>1;
    pushdown(rt,l,r);
    if(x<=mid) modify_add(rt<<1,l,mid,x,y);
    if(y>mid) modify_add(rt<<1|1,mid+1,r,x,y);
    sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod;
}
void modify_mul(int rt,int l,int r,int x,int y)
{
    if(x>y) return;
    if(x<=l&&r<=y) return add_sign_mul(rt,l,r,2);
    int mid=(l+r)>>1;
    pushdown(rt,l,r);
    if(x<=mid) modify_mul(rt<<1,l,mid,x,y);
    if(y>mid) modify_mul(rt<<1|1,mid+1,r,x,y);
    sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod;
}
ll query(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y) return sum[rt];
    int mid=(l+r)>>1;
    pushdown(rt,l,r);
    ll ret=0;
    if(x<=mid) ret+=query(rt<<1,l,mid,x,y);
    if(y>mid) ret+=query(rt<<1|1,mid+1,r,x,y);
    return ret%mod;
}

int main()
{
    freopen("multiset.in","r",stdin);
    freopen("multiset.out","w",stdout);
    read(n);read(q);
    for(int i=0,t=N-1;i<=t;++i) sign_mul[i]=1;
    while(q--)
    {
        int opt,l,r,x;
        read(opt);read(l);read(r);
        if(opt==1)
        {
            read(x);//向[l,r]加入x
            int L=l,R=r;
            int dl=l;//dl表示现在应该处理的最左边 
            IT it=col[x].find(SXK(l,r));//找到第一个有交集的区间 
            while( it!=col[x].end() )
            {
                modify_add(1,1,n,dl,it->l - 1);
                modify_mul(1,1,n,Max(it->l,dl),Min(it->r,r));
                dl=it->r+1;
                L=Min(L,it->l);
                R=Max(R,it->r);
                col[x].erase(it);
                it=col[x].find(SXK(l,r));
            }
            modify_add(1,1,n,dl,r);//处理最后一段 
            ////这一段可以有更简单的写法,时间差不多
            col[x].insert(SXK(L,R));
        }
        else printf("%lld\n",query(1,1,n,l,r));
    }
    return 0;
}

2. Dynamic prescription segment tree

Obviously, the reason for a color explosion of a segment tree will be opened a lot of wasted space, direct dynamic optimization can be a prescription segment tree (So Easy

Guess you like

Origin www.cnblogs.com/Chtholly/p/11574190.html