SD provincial team training 2019Day9 of "tapping the inverted Little Witch"

Flip pat little witch (flipflap) ([Ynoi2014] exposure of heaven Mori)

Title Description

Segment tree is a special binary tree, the following properties:
for each point and an interval corresponding to, and has a weight integer;
root node corresponding to the interval is [1, n];
if the interval corresponding to the point a is [L, r], and l <r, then its left child and right child, respectively, correspond to regions
between [l, m] and [m + 1, r], where m = floor ((l + r ) / 2) (floor represented down);
if a point corresponding to the interval is [l, r], and l = r, then this point is a leaf;
if a point is not a leaf, then its weight is equal to the weight of the left child and right child Sum.
You need to maintain a segment tree, leaves the initial weight is zero, the following operations will be m:
Operation 1: gives l, r, a, for each of the x (l≤x≤r), the [X , x] corresponding weights plus leaves a,
the weight of the non-leaf nodes corresponding change;
operation 2: given l, r, a, ask how many segments the tree, satisfy this interval is corresponding to the point [l, r]
contained, and the less weight a.

practice

If we maintain a sequence but not the tree line, our operations will become what it?

1. interval plus

2. Ask how many numbers in the interval smaller than x

This seems to be a classic problem of block sequence into ah ...... We \ (O (\ sqrt {n }) \) blocks, and each block maintains a block number and the sorted array a marker addition, we modified when the reconstruction of scattered violence block, for our entire direct marking

Then when we asked for a piece of the corner of violence and direct-half on the line

The complexity of doing so is \ (O (NlogN \ sqrt { N}) \) of

Next we found this stuff segment tree does not move, we found that the value of the time interval vary + x segment tree each node \ (len × x \) where \ (len \) is the length of the segment tree node even if we discuss the line for size classification tree node, just want to apply the block algorithm, we will find that just a simple addition interval can destroy our orderly nature

But len ​​value for each node since we mentioned you will find a very interesting property

When the length of our entire range is 2 to the power of time we will find len values ​​only log species ...... Obviously this is of course very

So let us look into the tree line in general, we find an interesting nature broth can be obtained by playing table, the length of the segment tree is less than \ (10 ^ 5 \) time, this segment tree up to 33 species (should this number may be slightly floating) essentially different nodes length

So we can look equal to the length of a node as a node pull-out sequence

So it seems that we can for each different interval length and then to run just on violence in the sequence ......

When we perform the specific point in terms of section \ ((l, r) \ ) when x is added, we enumerate each of the different lengths nodes \ (len \) , then we put all of the nodes in the length len left point sorted (in fact, may be the right end, after all the same length as a certain node are mutually exclusive, the segment tree section intersecting relationship not exist) of these nodes to form a sequence of

At this time, we found that only increased lll and closer rrr node value is not \ (len × x \) as r l and may not completely contain the node,

Other by weight of (l, r) (l, r) (l, r) is fully contained in the node must increase \ (len × XL \) , so \ ((l, r) \ ) interval \ (+ x \) becomes two single point interval plus a modify operation and operations that we can apply of course in the block sequence algorithm

And of course, we can enumerate the query node length, it remains patchy block violence and then find the answers on the half piece on it

The complexity of the algorithm looks like we are \ (O (Nlog ^ 2 { n} \ sqrt {N}) \) but we found two different nodes up to the length of each segment tree level

So we find that our first operation complexity is actually \ (\ sum_ {i} \ sqrt {\ frac {n} {2 ^ {i}}} (log (n) -i) \) , and this somewhat similar thing click complexity will find it actually \ (O (\ sqrt {N } logn) \)

Just a few times just slightly larger constant, so the overall complexity is our \ (O (N \ sqrt { N} logn) \)

He said a very nice actually write you find this block is not an ordinary and more details and memory allocation is very very big head ......

Etc. Once you finally finish line of 140 + code tone you find your tle the ......

If the simple realization of the above algorithm is clearly inconsistent with ynoi style

Every time we find scattered blocks to add when this block are some of the elements + va, then the relative orderliness unchanged between these elements, so we can use instead of sort merge to reconstruct the entire block, such complexity reconstruction becomes \ (O (n) \)

Modifications to a single point of violence this point we inserted into the original ordered sequence on the line, or you can continue to swap until you find a suitable location complexity still \ (O (n) \)

Then we can look snake skin tone block length of the reduced complexity of our \ (O (N \ sqrt { Nlogn}) \)

Then we found this to pay up or tle, probably score is between 55-85

We also need to find a number of press inquiries terms of complexity, it is regrettable that the complexity of the inquiry does not continue to be squeezed ......

So we still honestly pruning Well ......

In fact, we only need a very simple pruning can live this question, ask the judge for the maximum value of x is greater than or less than the minimum, if one of two conditions are met Returns 0 or block long, otherwise we will vigorously bipartite

This proved quite pruning so that, then we can pass this problem the ~

Code

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;const int N=1e5+10;typedef long long ll;int n;int m;
namespace INPUT_SPACE{//快读卡常版
    const int BS=(1<<24)+5;char Buffer[BS],*HD,*TL;
    char gc() { if(HD==TL) TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);return (HD==TL)?EOF:*HD++; }
    inline int inn()//读入
    {
        int x,ch,sgn=1;while(((ch=gc())<'0'||ch>'9')&&ch!='-');
        if(ch=='-') sgn=-1,x=0;else x=ch^'0';
        while((ch=gc())>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');
        return x*sgn;
    }
}using INPUT_SPACE::inn;
template <typename T>//这里直接用指针+数组分配内存 
inline void gm(T* & p,int siz,T* & op){op=p;p=p+siz+1;}
ll* S_t;int* A_t;ll S_bas[15*N];int A_bas[20*N];int q[N];ll* SA;
inline bool cmp(int x,int y){return SA[x]<SA[y];}
struct blk
{
    ll* a;int* sr;int* sr1;int siz;ll add;int pl;int pr;
    inline ll& operator [](const int& x){return a[x];}
    inline void ih()//初始化内存 
    {
        gm(S_t,siz,a);gm(A_t,siz,sr);gm(A_t,siz,sr1);
        for(int i=1;i<=siz;i++)sr[i]=i;
    }
    inline void rebuild(int l,int r,int pos)//归并 
    {
        for(int i=1;i<=siz;i++)a[i]+=add;add=0;
        int hd1=0;int hd=0;int op=0;
        for(int i=1;i<=siz;i++)
            if(sr[i]!=pos)((l<=sr[i]&&sr[i]<=r)?sr[++hd1]:q[++hd])=sr[i];
        int i=1;int j=1;
        while(i<=hd1&&j<=hd)sr1[++op]=((a[sr[i]]<a[q[j]])?sr[i++]:q[j++]);
        while(i<=hd1)sr1[++op]=sr[i++];while(j<=hd)sr1[++op]=q[j++];
        int ins=1;
        if(ins<=siz-1&&a[sr1[1]]<a[pos])
        {
            int l=1;int r=siz-1;
            while(l!=r){int mid=(l+r+1)>>1;if(a[sr1[mid]]<a[pos])l=mid;else r=mid-1;}
            ins=l+1;
        }for(int i=1;i<ins;i++)sr[i]=sr1[i];sr[ins]=pos;
        for(int i=ins;i<=siz-1;i++)sr[i+1]=sr1[i];
    }
    inline void brurebuild()
    {for(int i=1;i<=siz;i++)a[i]+=add;add=0;SA=a;sort(sr+1,sr+siz+1,cmp);}
    inline int qry(ll x)//询问 
    {
        int l=0;int r=siz;x-=add;
        if(x<a[sr[1]])return 0;if(x>=a[sr[siz]])return siz;
        while(l!=r){int mid=(l+r+1)>>1;if(a[sr[mid]]<=x)l=mid;else r=mid-1;}
        return l;
    }
    inline int brucalc(int l,int r,ll x)
    {int ret=0;x-=add;for(int i=l;i<=r;i++)ret+=(a[i]<=x);return ret;}
    inline void lb_add(ll del){add+=del;} 
}B_bas[N];blk* B_t;
struct blk_arr
{
    int tot;int* bi;int* bj;blk* bl;int* al;int* ar;int gl[N];int gr[N];int B;
    inline void ih()//分配内存 
    {
        gm(A_t,tot,bi);gm(A_t,tot,bj);gm(A_t,tot,al);gm(A_t,tot,ar);B=sqrt(tot)*1.3;
        for(int i=1;i<=tot;i++)bi[i]=(i-1)/B+1;for(int i=1;i<=tot;i++)bj[i]=(i-1)%B+1;
        gm(B_t,bi[tot],bl);for(int i=1;i<bi[tot];i++)bl[i].siz=B;
        bl[bi[tot]].siz=((tot%B)?tot%B:B);
        for(int i=1;i<=bi[tot];i++)bl[i].ih();tot=0;
    }
    inline void pb(const int& l,const int& r){al[++tot]=l;ar[tot]=r;}
    inline void calcg()//这里预处理的实际询问的点和序列上的点的映射 
    {
        for(int i=1;i<=n+1;i++)gl[i]=0x3f3f3f3f;for(int i=1;i<=tot;i++)gl[ar[i]]=i;
        for(int i=1;i<=tot;i++)gr[al[i]]=i;for(int i=n;i>=1;i--)gl[i]=min(gl[i],gl[i+1]);
        for(int i=1;i<=n;i++)gr[i]=max(gr[i],gr[i-1]);
    }
    inline bool aju(int& l,int& r)
    {r=min(r,ar[tot]);l=max(l,al[1]);return (l<=r);}
    inline void stadd(int l,int r,ll x,ll va)//分各种情况讨论 
    {
        if(aju(l,r)==false)return;int tl=gl[l];int tr=gr[r];if(tl>tr)return;
        l=max(l,al[tl]);r=min(r,ar[tr]);
        if(tl==tr){bl[bi[tl]][bj[tl]]+=(r-l+1)*x;bl[bi[tl]].rebuild(0,0,bj[tl]);return;}
        int p1=bi[tl];int p2=bi[tr];
        bl[p1][bj[tl]]+=(ar[tl]-l+1)*x;bl[p2][bj[tr]]+=(r-al[tr]+1)*x;
        if(p1==p2){for(int i=tl+1;i<tr;i++)bl[p1][bj[i]]+=va;bl[p1].brurebuild();return;}
        for(int i=tl+1;bi[i]==p1;i++)bl[p1][bj[i]]+=va;
        for(int i=tr-1;bi[i]==p2;i--)bl[p2][bj[i]]+=va;
        bl[p1].rebuild(bj[tl]+1,bl[p1].siz,bj[tl]);
        bl[p2].rebuild(1,bj[tr]-1,bj[tr]);
        for(int i=p1+1;i<p2;i++)bl[i].lb_add(va);
    }
    inline int qry(int l,int r,ll x)//询问也是分情况讨论 
    {
        if(aju(l,r)==false)return 0;int tl=gl[l];int tr=gr[r];
        if(l>al[tl])tl++;if(r<ar[tr])tr--;if(tl>tr)return 0;
        int p1=bi[tl];int p2=bi[tr];
        if(p1==p2){return bl[p1].brucalc(bj[tl],bj[tr],x);}int ret=0;
        ret=bl[p1].brucalc(bj[tl],bl[p1].siz,x)+bl[p2].brucalc(1,bj[tr],x);
        for(int i=p1+1;i<p2;i++)ret+=bl[i].qry(x);return ret;
    }
}ds[35];int lim[35];int cnt;
inline void dfs1(int l,int r)//预先分配size 
{
    if(l>r)return;int va=r-l+1;int mid=(l+r)>>1;
    for(int i=1;i<=cnt;i++)if(lim[i]==va){ds[i].tot++;goto ed;}
    lim[++cnt]=va;ds[cnt].tot++;
    ed:;if(r!=l){dfs1(l,mid);dfs1(mid+1,r);}
}
inline void dfs2(int l,int r)//处理区间 
{
    if(l>r)return;int va=r-l+1;int mid=(l+r)>>1;
    for(int i=1;i<=cnt;i++)if(lim[i]==va){ds[i].pb(l,r);break;}
    if(r!=l){dfs2(l,mid);dfs2(mid+1,r);}
}
int main()
{
//  freopen("tst.txt","r",stdin);freopen("run.txt","w",stdout);
    S_t=S_bas;A_t=A_bas;B_t=B_bas;n=inn();m=inn();
    dfs1(1,n);for(int i=1;i<=cnt;i++)ds[i].ih();dfs2(1,n);
    for(int i=1;i<=cnt;i++)ds[i].calcg();
    for(int rd=1,tp,l,r,x;rd<=m;rd++)
    {
        tp=inn();l=inn();r=inn();x=inn();
        if(tp==1){for(int i=1;i<=cnt;i++)ds[i].stadd(l,r,x,(ll)lim[i]*x);}
        else 
        {
            int ret=0;for(int i=1;i<=cnt;i++)ret+=ds[i].qry(l,r,x);
            printf("%d\n",ret);
        }
    }return 0;//拜拜程序~ 
}

Guess you like

Origin www.cnblogs.com/water-lift/p/10993793.html