• 2019南昌网络赛  I. Yukino With Subinterval 树状数组套线段树


    I. Yukino With Subinterval

    题目链接:

    Problem Descripe

    Yukino has an array (a_1, a_2 cdots a_n). As a tsundere girl, Yukino is fond of studying subinterval.

    Today, she gives you four integers $l, r, x, y $, and she is looking for how many different subintervals ([L, R]) are in the interval ([l, r])that meet the following restraints:

    1. (a_L =a_{L+1} =cdots=a_R), and for any $ iin [L,R], x le a_i le y$.
    2. The length of such a subinterval should be maximum under the first restraint.

    Note that two subintervals ([L_1,R_1] , [L_2,R_2]) are different if and only if at least one of the following formulas is true:

    1. (L1 cancel= L2)
    2. (R1 cancel= R2)

    Yukino, at the same time, likes making tricks. She will choose two integers (pos,v), and she will change (a_{pos}) to (v).

    Now, you need to handle the following types of queries:

    • (1 pos v) : change (a_{pos}) to $v $
    • (2) (l r x y): print the number of legal subintervals in the interval ([l, r])

    Input

    The first line of the input contains two integers (n, m (1 le n, m le 2 imes 10^5))– the numbers of the array and the numbers of queries respectively.

    The second line of the input contains nnn integers (a_i (1 le a_i le n)).

    For the next mmm line, each containing a query in one of the following queries:

    • (1) (pos) (v (1 le pos, v le n)): change (a_{pos}) to (v)
    • (2 l r x y (1 le l le r le n) (1 le x le y le n)): print the number of legal subintervals in the interval ([l,r])

    Output

    For each query of the second type, you should output the number of legal subintervals in the interval ([l, r]).

    样例输入

    6 3
    3 3 1 5 6 5
    2 2 3 4 5
    1 3 2
    2 1 6 1 5

    样例输出

    0
    4

    样例解释

    For the first operations, there are (3) different subintervals (([2, 2],[3, 3],[2,3]))in the interval ([2, 3]), but none of them meets all the restraints.

    For the third operations, the legal subintervals in interval ([1, 6]) are: ([1, 2], [3, 3], [4, 4], [6, 6])

    Notes that although subintervals ([1,1]) and ([2,2]) also meet the first restraint, we can extend them to subinterval ([1, 2]). So the length of them is not long enough, which against the second one.

    题意

    给你一个序列,提供两种操作

    • (1) (pos) (v (1 le pos, v le n)): 将 (a_{pos}) 改为 (v)
    • (2 l r x y (1 le l le r le n) (1 le x le y le n)): 输出([l,r]) 中权值(in [x,y]) 的个数。特别注意一段连续相同的数只算一次

    题解

    树套树(n)年前打的,早就忘了,于是直接跳过,其实这就是一道可修改区间第k大模板题吧,如果不会的可以去luogu学习一下。

    模板传送门:https://www.luogu.org/problem/P3380

    这题唯一要解决的就是怎么处理连续段只算一次的问题了。我是树状数组套线段树,于是如果(a[i]=a[i-1])那么就不处理。

    还有几个需要注意的地方

    1. 如果改变了(a[i])的值,记得更改(a[i-1])(a[i+1])
    2. 对于区间([l,r]),记得特判(a[l]),可能(a[l]=a[l-1]),但是这时也要算

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define INF 0x7f7f7f7f
    #define N 200050
    template<typename T>void read(T&x)
    {
        ll k=0; char c=getchar();
        x=0;
        while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
        if (c==EOF)exit(0);
        while(isdigit(c))x=x*10+c-'0',c=getchar();
        x=k?-x:x;
    }
    void read_char(char &c)
    {while(!isalpha(c=getchar())&&c!=EOF);}
    int n,m,treeNode;
    int a[N],ql[20],qr[20];
    struct Tree{int ls,rs,sum;}tr[N*150];
    void update(int&x,int p,int tt,int l,int r)
    {
        if (x==0)x=++treeNode;
        tr[x].sum+=tt;
        if (l==r)return;
        int mid=(l+r)>>1;
        if (p<=mid)update(tr[x].ls,p,tt,l,mid);
        else update(tr[x].rs,p,tt,mid+1,r);
    }
    void change(int x,int p,int tt)
    {while(x<=n)update(x,p,tt,1,n+1),x+=x&-x;}
    void getRt(int l,int r)
    {
        ql[0]=qr[0]=0;
        while(l)ql[++ql[0]]=l,l-=l&-l;
        while(r)qr[++qr[0]]=r,r-=r&-r;
    }
    int getSum()
    {
        int ans=0;
        for(int i=1;i<=ql[0];i++)ans-=tr[tr[ql[i]].ls].sum;
        for(int i=1;i<=qr[0];i++)ans+=tr[tr[qr[i]].ls].sum;
        return ans;
    }
    void move_L()
    {
        for(int i=1;i<=ql[0];i++)ql[i]=tr[ql[i]].ls;
        for(int i=1;i<=qr[0];i++)qr[i]=tr[qr[i]].ls;
    }
    void move_R()
    {
        for(int i=1;i<=ql[0];i++)ql[i]=tr[ql[i]].rs;
        for(int i=1;i<=qr[0];i++)qr[i]=tr[qr[i]].rs;
    }
    int _Rank(int p,int l,int r)
    {
        if (l==r)return 0;
        int mid=(l+r)>>1,tp=getSum();
        if (p<mid){move_L();return _Rank(p,l,mid);}
        move_R(); return tp+_Rank(p,mid+1,r);
    }
    int Rank(int l,int r,int k)
    {
        getRt(l-1,r);
        return _Rank(k-1,1,n+1);
    }
    void work()
    {
        int id,pos,v,l,r,x,y;
        read(n); read(m);
        treeNode=n;
        for(int i=1;i<=n;i++)read(a[i]);
        for(int i=1;i<=n;i++)if (a[i]!=a[i-1])change(i,a[i],1);
        for(int i=1;i<=m;i++)
        {
            read(id);
            if (id==1)
            {
                read(pos); read(v);
                if (a[pos]!=a[pos-1])change(pos,a[pos],-1);
                if (v!=a[pos-1])change(pos,v,1);
                if (a[pos]==a[pos+1])change(pos+1,a[pos+1],1);
                if (v==a[pos+1])change(pos+1,a[pos+1],-1);
                a[pos]=v;
            }
            if (id==2)
            {
                read(l); read(r); read(x); read(y);
                int ans=-Rank(l,r,x)+Rank(l,r,y+1);
                if (a[l]==a[l-1]&&x<=a[l]&&a[l]<=y)ans++;
                printf("%d
    ",ans);
            }
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("aa.in","r",stdin);
    #endif
      work();
    }
    
    
  • 相关阅读:
    并发编程之多线程(理论部分)
    基于TCP和UDP的socket
    ajax笔记 显示出所城市名称 ShowCity.aspx Html代码
    蒸饭的纱布
    ajax 笔记--不刷新实现简单的留言版 guestBook
    从表的第几条取到第几条记录
    在asp.net添加数据到XML里去
    ajax 笔记-- 写了一个不用刷新就能实现--用户名验证的例子
    今天生日
    ajax 笔记不用刷新实现数据的分页显示
  • 原文地址:https://www.cnblogs.com/mmmqqdd/p/11508864.html
Copyright © 2020-2023  润新知