数据结构练习

数据结构练习

[NOI2021] 密码箱

这么说Quack大爷就有队爷水平了

首先考虑\(f\)是个线性变换

这里对于\(\dfrac{x}{y}\rightarrow \dfrac{y}{x}+a_i\),第\(i\)个元素可以用矩阵表示

\[\left [ \begin{matrix} x& y \\ 0& 0 \\ \end{matrix} \right ] \times\left [ \begin{matrix} a_i& 1 \\ 1& 0 \\ \end{matrix} \right ] \]

于是这里我们可以把序列拉成一个矩阵,但这是不够的,因为原题要对操作序列操作

考虑把每个操作也看作矩阵

对于\(W\),很明显就是左乘

\[\left [ \begin{matrix} 1& 1 \\ 0& 1 \\ \end{matrix} \right ] \]

对于\(E\),手完一下就能发现其实都可以看作减一后在后面填两个数

那其实就相当于左乘

\[\left [ \begin{matrix} 1& 1 \\ 1& 0 \\ \end{matrix} \right ]\times\left [ \begin{matrix} 1& 1 \\ 1& 0 \\ \end{matrix} \right ]\times \left [ \begin{matrix} 1& -1 \\ 0& 1 \\ \end{matrix} \right ]=\left [ \begin{matrix} 2& -1 \\ 1& 0 \\ \end{matrix} \right ] \]

用平衡树维护即可,细节有点多

#include<bits/stdc++.h>
#define ls Tree[p].lc
#define rs Tree[p].rc
using namespace std;
void read(int &x) {
    x = 0;
    int f = 1;
    char s = getchar();
    while (s > '9' || s < '0') {
        if (s == '-')
            f = -1;
        s = getchar();
    }
    while (s >= '0' && s <= '9') {
        x = (x << 3) + (x << 1) + (s - '0');
        s = getchar();
    }
    x *= f;
}
void write(int x) {
    if (x < 0) {
        putchar('-');
        x = (~x) + 1;
    }
    if (x > 9) {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}
const int MOD=998244353;
const int MAXN=2e5+5;
struct Martix{
    int val[2][2];
    void clear()
    {
        memset(val,0,sizeof(val));
    }
    void init()
    {
        clear();
        for(int i=0;i<2;i++)
        {
            val[i][i]=1;
        }
        return;     
    }
    void print()
    {
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<2;j++)
            {
                printf("%d ",val[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    Martix operator*(const Martix x)const{
        Martix Res;
        Res.clear();
        for(int k=0;k<2;k++)
        {
            for(int i=0;i<2;i++)
            {
                for(int j=0;j<2;j++)
                {
                    Res.val[i][j]=((long long)Res.val[i][j]+((long long)val[i][k]*x.val[k][j])%MOD)%MOD;
                }
            }
        }
        return Res;
    }  
}A,B,C;
struct FHQ_node{
    int lc,rc;
    int cnt;
    int Siz;
    int Key;
    Martix dt[2][2],val[2];  
    int lazy_rev;
    int lazy_roll;
};
struct FHQ{
    FHQ_node Tree[MAXN];
    int root;
    int cnt_node;
    int New(int op)
    {
        ++cnt_node;
        Tree[cnt_node].cnt=1;
        Tree[cnt_node].Siz=1;
        Tree[cnt_node].lazy_rev=0;
        Tree[cnt_node].lazy_roll=0;
        Tree[cnt_node].lc=0;
        Tree[cnt_node].rc=0;
        Tree[cnt_node].Key=rand();
        Tree[cnt_node].dt[op][0]=Tree[cnt_node].dt[op][1]=Tree[cnt_node].val[op]=A;
        Tree[cnt_node].dt[op^1][0]=Tree[cnt_node].dt[op^1][1]=Tree[cnt_node].val[op^1]=B;
        return cnt_node;
    }
    void push_up(int p)
    {
        Tree[p].Siz=Tree[ls].Siz+Tree[rs].Siz+Tree[p].cnt;

        Tree[p].dt[0][0].init();
        if(ls)
        {
            Tree[p].dt[0][0]=Tree[p].dt[0][0]*Tree[ls].dt[0][0];
        }    
        Tree[p].dt[0][0]=(Tree[p].dt[0][0]*Tree[p].val[0]);
        if(rs)
        {
            Tree[p].dt[0][0]=Tree[p].dt[0][0]*Tree[rs].dt[0][0];
        }   

        Tree[p].dt[1][0].init();
        if(ls)
        {
            Tree[p].dt[1][0]=Tree[p].dt[1][0]*Tree[ls].dt[1][0];
        }    
        Tree[p].dt[1][0]=(Tree[p].dt[1][0]*Tree[p].val[1]);
        if(rs)
        {
            Tree[p].dt[1][0]=Tree[p].dt[1][0]*Tree[rs].dt[1][0];
        }   

        Tree[p].dt[0][1].init();
        if(rs)
        {
            Tree[p].dt[0][1]=Tree[p].dt[0][1]*Tree[rs].dt[0][1];
        }    
        Tree[p].dt[0][1]=(Tree[p].dt[0][1]*Tree[p].val[0]);
        if(ls)
        {
            Tree[p].dt[0][1]=Tree[p].dt[0][1]*Tree[ls].dt[0][1];
        }  

        Tree[p].dt[1][1].init();
        if(rs)
        {
            Tree[p].dt[1][1]=Tree[p].dt[1][1]*Tree[rs].dt[1][1];
        }    
        Tree[p].dt[1][1]=(Tree[p].dt[1][1]*Tree[p].val[1]);
        if(ls)
        {
            Tree[p].dt[1][1]=Tree[p].dt[1][1]*Tree[ls].dt[1][1];
        }    
    }
    void push_down(int p)
    {
        if(Tree[p].lazy_roll)
        {
            swap(ls,rs);
            swap(Tree[ls].dt[0][0],Tree[ls].dt[0][1]);
            swap(Tree[ls].dt[1][0],Tree[ls].dt[1][1]);
            swap(Tree[rs].dt[0][0],Tree[rs].dt[0][1]);
            swap(Tree[rs].dt[1][0],Tree[rs].dt[1][1]);
            Tree[ls].lazy_roll^=1;
            Tree[rs].lazy_roll^=1;
            Tree[p].lazy_roll=0;
        }
        if(Tree[p].lazy_rev)
        {
            swap(Tree[ls].dt[0][0],Tree[ls].dt[1][0]);
            swap(Tree[ls].dt[0][1],Tree[ls].dt[1][1]);
            swap(Tree[ls].val[0],Tree[ls].val[1]);
            swap(Tree[rs].dt[0][0],Tree[rs].dt[1][0]);
            swap(Tree[rs].dt[0][1],Tree[rs].dt[1][1]);
            swap(Tree[rs].val[0],Tree[rs].val[1]);
            Tree[ls].lazy_rev^=1;
            Tree[rs].lazy_rev^=1;
            Tree[p].lazy_rev=0;
        }
    }
    void Split(int p,int val,int &x,int &y)
	{
		if(!p)
		{
			x=0;
			y=0;
			return;
		}
		push_down(p);
		if(Tree[ls].Siz+Tree[p].cnt<=val)
		{
			x=p;
			Split(rs,val-Tree[ls].Siz-Tree[p].cnt,rs,y);
		}
		else
		{
			y=p;
			Split(ls,val,x,ls);
		}
		push_up(p);
	}
    int Merge(int x,int y)
	{
		if((!x)||(!y))
		{
			return x+y;
		}
		if(Tree[x].Key<Tree[y].Key)
		{
			push_down(x); 
			Tree[x].rc=Merge(Tree[x].rc,y);
			push_up(x);
			return x;
		}
		else
		{
			push_down(y);
			Tree[y].lc=Merge(x,Tree[y].lc);
			push_up(y);
			return y;
		}
	}
    void Insert(int op)
    {
        root=Merge(root,New(op));
        return;
    }
    void Rev(int l,int r)
    {
        int lx,zx,rx;
        Split(root,l-1,lx,rx);
        Split(rx,r-l+1,zx,rx);
        swap(Tree[zx].dt[0][1],Tree[zx].dt[1][1]);
        swap(Tree[zx].dt[0][0],Tree[zx].dt[1][0]);
        swap(Tree[zx].val[0],Tree[zx].val[1]);
        Tree[zx].lazy_rev^=1;
        root=Merge(lx,Merge(zx,rx));
        return;
    }
    void Roll(int l,int r)
    {
        int lx,zx,rx;
        Split(root,l-1,lx,rx);
        Split(rx,r-l+1,zx,rx);
        swap(Tree[zx].dt[0][0],Tree[zx].dt[0][1]);
        swap(Tree[zx].dt[1][0],Tree[zx].dt[1][1]);
        Tree[zx].lazy_roll^=1;
        root=Merge(lx,Merge(zx,rx));
        return;
    }
}tree;
int n,q;
char S[MAXN];
char R[15];
int l,r;

int main()
{
    freopen("code.in","r",stdin);
    freopen("code.out","w",stdout);
    srand(time(0));
    
    A.val[0][0]=1;
    A.val[0][1]=1;
    A.val[1][0]=0;
    A.val[1][1]=1;

    B.val[0][0]=2;
    B.val[0][1]=MOD-1;
    B.val[1][0]=1;
    B.val[1][1]=0;
    
    C.val[0][0]=1;
    C.val[0][1]=1;
    C.val[1][0]=1;
    C.val[1][1]=0;
    read(n);
    read(q);
    scanf("%s",S);
    
    for(int i=0;i<n;i++)
    {
        if(S[i]=='W')
        {
            tree.Insert(0);
        }
        else
        {
            tree.Insert(1);
        }
    }
    printf("%d %d\n",(tree.Tree[tree.root].dt[0][1]*C).val[0][1],(tree.Tree[tree.root].dt[0][1]*C).val[0][0]);
    while(q--)
    {
        scanf("%s",R);
        if(R[0]=='A')
        {
            scanf("%s",R);
            if(R[0]=='W')
            {
                tree.Insert(0);
            }
            else
            {
                tree.Insert(1);
            }
        }
        else if(R[0]=='F')
        {
            read(l);
            read(r);
            tree.Rev(l,r);
        }
        else
        {
            read(l);
            read(r);
            tree.Roll(l,r);
        }
        printf("%d %d\n",(tree.Tree[tree.root].dt[0][1]*C).val[0][1],(tree.Tree[tree.root].dt[0][1]*C).val[0][0]);
    }
}

CF1588F Jumping Through the Array

这个条件看着很奇怪,不妨往分块上想

进一步,考虑操作分块

考虑如果没有操作\(3\),这里我们可以发现涉及到的环只有\(\sqrt n\)

这里我们就可以暴力计算每个操作对每个询问的影响,最后\(\sqrt n\)次暴力推平即可

如果有操作三,我们可以对点染色,可以发现每个交换点的前驱是跟在它一起的

实际上我们可以把它的极长空白前驱放在一起为一个联通块

这里对于操作\(2\)这里我们操作一次大概是直接走前驱,只有\(\sqrt n\)

然后似乎就完了,注意实现,有点卡常

#include<bits/stdc++.h>
void read(int &x) {
    x = 0;
    int f = 1;
    char s = getchar();
    while (s > '9' || s < '0') {
        if (s == '-')
            f = -1;
        s = getchar();
    }
    while (s >= '0' && s <= '9') {
        x = (x << 3) + (x << 1) + (s - '0');
        s = getchar();
    }
    x *= f;
}
void write(int x) {
    if (x < 0) {
        putchar('-');
        x = (~x) + 1;
    }
    if (x > 9) {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}
using namespace std;
const int MAXN=2e5+5;
int n,q;
long long a[MAXN];
long long sum[MAXN];
int P[MAXN];
int S[MAXN];
int clo[MAXN];
long long Add[MAXN];
struct Query{
    int op,l,r;
    int x,y;
}query[MAXN];
int op,l,r,x,y;
int Rk[1005];
int Tk[MAXN];
int Sz[1005][1005];
int Tot[MAXN];
int main()
{
    //  freopen("date.in","r",stdin);
    //  freopen("date.out","w",stdout);
    scanf("%d",&n);
    int Block=430;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }  
    for(int i=1;i<=n;i++)
    {
        sum[i]=sum[i-1]+a[i];
    }
    for(int i=1;i<=n;i++)
    {
        read(P[i]);
        S[P[i]]=i;
    }
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        read(op);
        if(op==1)
        {
            read(l);
            read(r);
            query[i].op=1;
            query[i].l=l;
            query[i].r=r;
        }
        else if(op==2)
        {
            read(x);
            read(y);
            query[i].op=2;
            query[i].x=x;
            query[i].y=y;
        }
        else if(op==3)
        {
            read(x);
            read(y);
            query[i].op=3;
            query[i].x=x;
            query[i].y=y;
        }
    }
    for(int L=1;L<=q;L+=Block)
    {
        int R=min(L+Block-1,q);
        for(int i=0;i<=n;i++)
        {
            clo[i]=0;
            Tk[i]=0;
        }
        for(int i=L;i<=R;i++)
        {
            if(query[i].op==2)
            {
                clo[query[i].x]=query[i].x;
            }
            if(query[i].op==3)
            {
                clo[query[i].x]=query[i].x;
                clo[query[i].y]=query[i].y;
            }
        }
        int cnt_clo=0;

        for(int i=1;i<=n;i++)
        {
            if(clo[i]==i)
            {
                Rk[++cnt_clo]=i;
                int Now=S[i];
                while((!clo[Now]))
                {
                    clo[Now]=i;
                    Now=S[Now];
                }
            }
        }
        int cnt_q=0;
        for(int i=L;i<=R;i++)
        {
            if(query[i].op==1)
            {
                Tk[query[i].l-1]=++cnt_q;
                Tk[query[i].r]=++cnt_q;
            }   
        }
        if(Tk[0])
        {
            for(int i=1;i<=cnt_clo;i++)
            {
                Sz[Tk[0]][i]=0;
            }
        }
        
        for(int i=1;i<=n;i++)
        {
            Tot[clo[i]]++;
            if(Tk[i])
            {
                for(int j=1;j<=cnt_clo;j++)
                {
                    Sz[Tk[i]][j]=Tot[Rk[j]];
                }
            }
        }
        for(int i=L;i<=R;i++)
        {
            if(query[i].op==1)
            {
                l=query[i].l;
                r=query[i].r;
                long long Rp=(sum[r]-sum[l-1]);
                for(int j=1;j<=cnt_clo;j++)
                {
                    int Pl=Sz[Tk[l-1]][j];
                    int Pr=Sz[Tk[r]][j];
                    int Ln=Pr-Pl;
                    Rp=(Rp+((long long)Ln*Add[Rk[j]]));
                }
                printf("%lld\n",Rp);
            }
            else if(query[i].op==2)
            {
                int Now=clo[P[query[i].x]];
                while(1)
                {
                    Add[Now]+=query[i].y;
                    
                    if(Now==clo[query[i].x])
                    {
                        break;
                    }
                    Now=clo[P[Now]];
                }
                
            }
            else
            {
                swap(P[query[i].x],P[query[i].y]);
                S[P[query[i].x]]=query[i].x;
                S[P[query[i].y]]=query[i].y;
            }
        }
        for(int i=1;i<=n;i++)
        {
            a[i]=a[i]+Add[clo[i]];
            sum[i]=sum[i-1]+a[i];
        }
        for(int i=1;i<=n;i++)
        {
            Add[i]=0;
            Rk[min(i,1000)]=0;
            Tot[i]=0;
        }
    }
}

CF679E Bear and Bad Powers of 42

维护每个数到下一个\(42\)次幂的距离

可以发现直接看每次加的是否会超出当前距离的最小值

超出了就暴力改,可以发现每个元素改的次数很少

具体时间复杂度分析就是把线段树每个节点还可以改多少看作势能,可以发现每次会用\(O(1)\)的时间解决\(O(1)\)的势能,而一次赋值只会增加\(O(\log_2(n))\)的势能

注意实现,好像有点卡常

我要做DJ小姐的狗·

#include<bits/stdc++.h>
#define int long long
#define ls 2*p
#define rs 2*p+1
using namespace std;
const int MAXN=1e5+5;
int n,q;
long long a[MAXN];
long long R[MAXN];
int op,l,r,x;
long long B[15];
struct Seg{
    int l,r;
    long long date;
    long long Ori_lazy;
    long long Add;
    long long Ori;
}Tree[MAXN*4];
int get(int x) {
	return *lower_bound(B, B + 12, x) - x;
}
void push_up(int p)
{
    Tree[p].date=min(Tree[ls].date,Tree[rs].date);
}
void push_down(int p)
{
    if(Tree[p].Ori_lazy!=0)
    {
        Tree[ls].Add=0;
        Tree[rs].Add=0;
        Tree[ls].Ori_lazy=Tree[p].Ori_lazy;
        Tree[rs].Ori_lazy=Tree[p].Ori_lazy;
        Tree[ls].date=get(Tree[p].Ori_lazy);
        Tree[rs].date=get(Tree[p].Ori_lazy);
        Tree[ls].Ori=Tree[p].Ori_lazy;
        Tree[rs].Ori=Tree[p].Ori_lazy;
        Tree[p].Ori_lazy=0;
    }
    if(Tree[p].Add!=0)
    {
        Tree[ls].date-=Tree[p].Add;
        Tree[ls].Ori+=Tree[p].Add;
        if(Tree[ls].Ori_lazy!=0)
        {
            Tree[ls].Ori_lazy+=Tree[p].Add;
        }
        else
        {
            Tree[ls].Add+=Tree[p].Add;            
        }


        Tree[rs].date-=Tree[p].Add;
        Tree[rs].Ori+=Tree[p].Add;
        if(Tree[rs].Ori_lazy!=0)
        {
            Tree[rs].Ori_lazy+=Tree[p].Add;
        }
        else
        {
            Tree[rs].Add+=Tree[p].Add;            
        }
        Tree[p].Add=0;
    }
}
void Build(int p,int l,int r)
{
    Tree[p].l=l;
    Tree[p].r=r;
    Tree[p].Add=0;
    Tree[p].Ori_lazy=0;
    if(l==r)
    {
        Tree[p].date=R[l];
        Tree[p].Ori=a[l];
        return;
    }
    int mid=(l+r)>>1;
    Build(ls,l,mid);
    Build(rs,mid+1,r);
    push_up(p);
}
void Update_add(int p,int l,int r,int x)
{
    if(Tree[p].l>=l&&Tree[p].r<=r)
	{
		Tree[p].Ori += x;
        Tree[p].date-=x;
        if(Tree[p].Ori_lazy!=0)
        {
            Tree[p].Ori_lazy+=x;
        }
        else
        {
            Tree[p].Add+=x;
        }
     	return;
    }
    push_down(p);
    int mid=(Tree[p].l+Tree[p].r)>>1;
    if(l<=mid)
    {
        Update_add(ls,l,r,x);
    }
    if(r>mid)
    {
        Update_add(rs,l,r,x);
    }
    push_up(p);
}
void Update_fill(int p,int l,int r,int x)
{
    if(Tree[p].l>=l&&Tree[p].r<=r)
    {
        Tree[p].Add=0;
        Tree[p].Ori=x;
        Tree[p].Ori_lazy=x;
        Tree[p].date=get(x);
        return;
    }
    push_down(p);
    int mid=(Tree[p].l+Tree[p].r)>>1;
    if(l<=mid)
    {
        Update_fill(ls,l,r,x);
    }
    if(r>mid)
    {
        Update_fill(rs,l,r,x);
    }
    push_up(p);
}

long long Query(int p,int x)
{
    if(Tree[p].l==Tree[p].r)
    {
        return Tree[p].Ori;
    }
    push_down(p);
    int mid=(Tree[p].l+Tree[p].r)>>1;
    if(x<=mid)
    {
        return Query(ls,x);
    }
    else
    {
        return Query(rs,x);
    }
}

void upd(int p) {
	if (Tree[p].date >= 0) {
		return ;
	} else if (Tree[p].l == Tree[p].r) {
		Tree[p].date = get(Tree[p].Ori);
        return ;
	}
	push_down(p);
	upd(p << 1);
	upd(p << 1 | 1);
	push_up(p);
}
signed main()
{
//    freopen("data.in","r",stdin);
//    freopen("data.out","w",stdout);
    B[0]=1;
    for(int i=1;i<=11;i++)
    {
        B[i]=((long long)B[i-1]*42);
    }

    scanf("%lld %lld",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        int Tp=lower_bound(B,B+11+1,a[i])-B;
        R[i]=B[Tp]-a[i];
    }
    int Cnt=0;
    Build(1,1,n);

    while(q--)
    {
        scanf("%lld",&op);
        if(op==1)
        {
            scanf("%lld",&x);
            printf("%lld\n",Query(1,x));
        }
        else if(op==2)
        {
            
            scanf("%lld %lld %lld",&l,&r,&x);
             Update_fill(1,l,r,x);
        }
        else
        {  
            scanf("%lld %lld %lld",&l,&r,&x);
            Update_add(1,l,r,x);
            upd(1);
            while(Tree[1].date==0)
            {
                Update_add(1,l,r,x);
                upd(1);
            }
        }
    }
}

[UR19]前进四

维护单调栈有一个\(log^2(n)\)的做法,这里肯定是不能再优化的

于是这里我们可以换一个角度看待问题

不妨枚举位置维护每个询问

考虑这里的单调栈的过程,我们发现从后往前,只要新添加的数小于当前最小值就会使答案\(+1\)

考虑用线段树维护时间轴,区间取\(min\)即可,似乎势能线段树只取\(min\)的时间复杂度是\(O(log(n))\)

话说4道题卡了3道题的常

#pragma GCC optimize("O2")
#pragma GCC optimize("O3")
#pragma GCC optimize("Og")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#define U 10000
#define N 1000012
#define INF 0x3f3f3f3f
#define MAX_READ 33554432
using namespace std;
inline int max(int x,int y){return (x>y)?x:y;}
char buf[MAX_READ],*l=buf;
inline int read()
{
	int X=0;char ch=0;while('0'>ch||ch>'9')ch=*(l++);
	while('0'<=ch&&ch<='9')X=(X<<3)+(X<<1)+(ch^48),ch=*(l++);return X;
}
char CH[12000012],nu[U][4],fnu[U][4];int cn=0,le[U];
inline void wr(int x){if(x<10000){memcpy(CH+cn,nu[x],le[x]);cn+=le[x];return;}int v=x/10000;wr(v);x-=v*10000;memcpy(CH+cn,fnu[x],4);cn+=4;}
#define ls p<<1
#define rs p<<1|1
using namespace std;
const int MAXN=1e6+5;
int n;
int q;
int x,y;
int op;
int Ne[MAXN];
int Hea[MAXN];
int Val[MAXN];
int A[MAXN];
int Nex[MAXN];
int Head[MAXN];
int Ans[MAXN];

struct Seg{
    int ms;
    int mx;
    int l,r;
    int add;
    int lazy;
}Tree[MAXN*4];
inline void push_up(int p)
{
    if(Tree[ls].mx==Tree[rs].mx)
    {
        Tree[p].mx=Tree[ls].mx;
        Tree[p].ms=max(Tree[ls].ms,Tree[rs].ms);
    }
    else if(Tree[ls].mx>Tree[rs].mx)
    {
        Tree[p].mx=Tree[ls].mx;
        Tree[p].ms=max(Tree[ls].ms,Tree[rs].mx);
    }   
    else
    {
        Tree[p].mx=Tree[rs].mx;
        Tree[p].ms=max(Tree[rs].ms,Tree[ls].mx);
    }
}
inline void push_down(int p)
{
    if(Tree[p].add)
    {
        int Mxc=max(Tree[ls].mx,Tree[rs].mx);
        if(Tree[ls].mx==Mxc)
        {
            Tree[ls].mx=Tree[p].lazy;
            Tree[ls].lazy=Tree[p].lazy;
            Tree[ls].add+=Tree[p].add;
        }
        if(Tree[rs].mx==Mxc)
        {
            Tree[rs].mx=Tree[p].lazy;
            Tree[rs].lazy=Tree[p].lazy;
            Tree[rs].add+=Tree[p].add;
        }
        Tree[p].add=0;
        Tree[p].lazy=0;
    }
}
inline void Build(int p,int l,int r)
{
    Tree[p].l=l;
    Tree[p].r=r;
    Tree[p].add=0;
    Tree[p].mx=0x3f3f3f3f;
    Tree[p].ms=0;
    if(l==r)
    {
        return;
    }
    int mid=(l+r)>>1;
    Build(ls,l,mid);
    Build(rs,mid+1,r);
}
inline void Update(int p,int l,int r,int k)
{
    if(l>r)
    {
        return;
    }
    if(Tree[p].mx<=k)
    {
        return;
    }
    if(Tree[p].l==Tree[p].r)
    {
        if(k<Tree[p].mx)
        {
            Tree[p].mx=k;
            Tree[p].add++;
        }
        return;
    }
    if(Tree[p].l>=l&&Tree[p].r<=r)
    {
        if(Tree[p].mx<=k)
        {
            return;
        }
        else if(k>Tree[p].ms)
        {
            Tree[p].mx=k;
            Tree[p].lazy=k;
            Tree[p].add++;
            return;
        }
    }
    push_down(p);
    int mid=(Tree[p].l+Tree[p].r)>>1;
    if(l<=mid)
    {
        Update(ls,l,r,k);
    }
    if(r>mid)
    {
        Update(rs,l,r,k);
    }
    push_up(p);
}
inline int Query(int p,int x)
{
    if(Tree[p].l==Tree[p].r)
    {
        return Tree[p].add;
    }
    push_down(p);
    int mid=(Tree[p].l+Tree[p].r)>>1;
    if(x<=mid)
    {
        return Query(ls,x);
    }
    else
    {
        return Query(rs,x);
    }
}
inline void PreGet(){int i,x;for(i=0;i<U;i++){for(x=i;x;x/=10)nu[i][le[i]++]=(x%10)^48;memcpy(fnu[i],nu[i],4);for(x=le[i];x<=3;++x)fnu[i][x]=48;reverse(nu[i],nu[i]+le[i]);reverse(fnu[i],fnu[i]+4);}nu[0][0]=48;le[0]=1;}
int main()
{
  PreGet();fread(buf,1,MAX_READ,stdin);
    n=read();
    q=read();
    for(int i=1;i<=n;i++)
    {
        x=read();
        A[i]=x;
        Hea[i]=q+1;
        Ne[q+1]=0;
    }
    for(int i=1;i<=q;i++)
    {
        op=read();
        if(op==1)
        {
            x=read();
            y=read();
            Val[i]=y;
            Ne[i]=Hea[x];
            Hea[x]=i;
        }
        else
        {
            x=read();
            Nex[i]=Head[x];
            Head[x]=i;
        }
    }
    Build(1,1,q);
    
    for(int i=n;i>=1;i--)
    {
        int Lap=q;
        for(int j=Hea[i];j;j=Ne[j])
        {
            int L=j;
            int Rx=Lap;
            if(j!=(q+1))
            {
                Update(1,max(L,1),Rx,Val[j]);
            }
            else
            {
                Update(1,1,Rx,A[i]);
            }
            
            Lap=j-1;
        }
        for(int j=Head[i];j;j=Nex[j])
        {
            Ans[j]=Query(1,j);
        }
    }
    for(int i=1;i<=q;i++)
    {
        if(Ans[i])
        {
            wr(Ans[i]),CH[cn++]='\n';
        }
    }
    fwrite(CH,1,cn,stdout);

}
posted @ 2023-07-06 09:28  kid_magic  阅读(16)  评论(0编辑  收藏  举报