zoukankan      html  css  js  c++  java
  • Acdream 1738 世风日下的哗啦啦族I 树套树

    世风日下的哗啦啦族I

    Time Limit: 20 Sec  Memory Limit: 256 MB

    题目连接

    http://acdream.info/problem?pid=1738

    Description

    "世风日下啊,女生不穿裙子的太少了"
    "这不是社会的进步吗(逃"
    "哎,是否可以建立一种结构统计一下各学院各专业各班级女生穿裙子的数量以及裙子的长度"
    "然后查询区间裙子最短值?"
    "并输出这个区间 穿这个裙子长度的妹子 有多少个?"
    "然后判断下在有风的情况下,多少妹子是安全的."


    "maya 哗啦啦族真是太可怕啦!"

    Input

    第一行 n,m表示n个妹子,m个操作
    第二行 a1 a2 a3 …… an,n个整数,表示妹子一开始的裙子长度,如果穿的是裤子,ai=-1
    下面m行:
    总共3种操作
    1 a b
    修改a妹子的裙子,变成b长度
    2 l r
    查询[l,r]区间的妹子最短的裙子长度,并输出有多少个妹子穿这个长度裙子的
    3 l r t
    输出[l,r]区间的妹子身穿裙子长度小于等于t的个数
    1<=n,m<=50000
    1<=a<=n
    1<=b<=50000
    1<=ai<=50000
    1<=l<=r<=n
    0<=t<=50000

    Output

    根据询问,输出答案

    具体看样例

    Sample Input

    3 3
    1 2 3
    1 1 4
    2 1 3
    3 1 3 2

    Sample Output

    2 1
    1

    HINT

    题意

    题解:

    啊,线段树套平衡树

    每个点套进去一颗平衡树

    然后搞呀搞

    好蛋疼……

    好麻烦……

    http://pan.baidu.com/s/1hqu4qBa

    代码:

    //qscqesze
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <sstream>
    #include <queue>
    #include <typeinfo>
    #include <fstream>
    #include <map>
    #include <stack>
    typedef long long ll;
    using namespace std;
    //freopen("D.in","r",stdin);
    //freopen("D.out","w",stdout);
    #define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
    #define maxn 200001
    #define mod 10007
    #define eps 1e-9
    int Num;
    char CH[20];
    //const int inf=0x7fffffff;   //нчоч╢С
    const int inf=0x3f3f3f3f;
    /*
    
    inline void P(int x)
    {
        Num=0;if(!x){putchar('0');puts("");return;}
        while(x>0)CH[++Num]=x%10,x/=10;
        while(Num)putchar(CH[Num--]+48);
        puts("");
    }
    */
    inline ll read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void P(int x)
    {
        Num=0;if(!x){putchar('0');puts("");return;}
        while(x>0)CH[++Num]=x%10,x/=10;
        while(Num)putchar(CH[Num--]+48);
        puts("");
    }
    //**************************************************************************************
    
    
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define LL long long
    #define REP(i,r,n) for(int i=r;i<=n;i++)
    #define RREP(i,n,r) for(int i=n;i>=r;i--)
    #define lson l,m,root<<1
    #define rson m+1,r,root<<1|1
    const int MAXN=5e4+100;
    
    struct SplayTree {
        int sz[MAXN*20];
        int ch[MAXN*20][2];
        int pre[MAXN*20];
        int top;
        int rt[MAXN<<2];
        inline void up(int x){
            sz[x]  = cnt[x]  + sz[ ch[x][0] ] + sz[ ch[x][1] ];
        }
        inline void Rotate(int x,int f){
            int y=pre[x];
            ch[y][!f] = ch[x][f];
            pre[ ch[x][f] ] = y;
            pre[x] = pre[y];
            if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;
            ch[x][f] = y;
            pre[y] = x;
            up(y);
        }
        inline void Splay(int x,int goal,int root){//将x旋转到goal的下面
            while(pre[x] != goal){
                if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x);
                else   {
                    int y=pre[x],z=pre[y];
                    int f = (ch[z][0]==y);
                    if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);
                    else Rotate(y,f),Rotate(x,f);
                }
            }
            up(x);
            if(goal==0) rt[root]=x;
        }
        inline void RTO(int k,int goal,int root){//将第k位数旋转到goal的下面
            int x=rt[root];
            while(sz[ ch[x][0] ] != k-1) {
                if(k < sz[ ch[x][0] ]+1) x=ch[x][0];
                else {
                    k-=(sz[ ch[x][0] ]+1);
                    x = ch[x][1];
                }
            }
            Splay(x,goal,root);
        }
        inline void vist(int x){
            if(x){
                printf("结点%2d : 左儿子  %2d   右儿子  %2d   %2d sz=%d
    ",x,ch[x][0],ch[x][1],val[x],sz[x]);
                vist(ch[x][0]);
                vist(ch[x][1]);
            }
        }
        inline void Newnode(int &x,int c){
            x=++top;
            ch[x][0] = ch[x][1] = pre[x] = 0;
            sz[x]=1; cnt[x]=1;
            val[x] = c;
        }
        inline void init(){
            top=0;
        }
        inline void Insert(int &x,int key,int f,int root){
            if(!x) {
                Newnode(x,key);
                pre[x]=f;
                Splay(x,0,root);
                return ;
            }
            if(key==val[x]){
                cnt[x]++;
                sz[x]++;
                return ;
            }else if(key<val[x]) {
                Insert(ch[x][0],key,x,root);
            } else {
                Insert(ch[x][1],key,x,root);
            }
            up(x);
        }
    
        void Del(int root){  //删除根结点
             if(cnt[rt[root]]>1)
             {
                cnt[rt[root]]--;
             }
             else
             {
                 int t=rt[root];
                 if(ch[rt[root]][1]) {
                     rt[root]=ch[rt[root]][1];
                     RTO(1,0,root);
                     ch[rt[root]][0]=ch[t][0];
                     if(ch[rt[root]][0]) pre[ch[rt[root]][0]]=rt[root];
                 }
                 else rt[root]=ch[rt[root]][0];
                 pre[rt[root]]=0;
             }
             up(rt[root]);
        }
        void findpre(int x,int key,int &ans){  //找key前趋
            if(!x)  return ;
            if(val[x] <= key){
                ans=x;
                findpre(ch[x][1],key,ans);
            } else
                findpre(ch[x][0],key,ans);
        }
        void findsucc(int x,int key,int &ans){  //找key后继
            if(!x) return ;
            if(val[x]>=key) {
                ans=x;
                findsucc(ch[x][0],key,ans);
            } else
                findsucc(ch[x][1],key,ans);
        }
        void findkey(int x,int key,int &ans)//找key
        {
            if(!x)return;
            if(val[x]==key)
                ans=x;
            else if(val[x]>key)
                findkey(ch[x][0],key,ans);
            else
                findkey(ch[x][1],key,ans);
        }
        //找第K大数
        inline int find_kth(int x,int k,int root){
            if(k<sz[ch[x][0]]+1) {
                return find_kth(ch[x][0],k,root);
            }else if(k > sz[ ch[x][0] ] + cnt[x] )
                return find_kth(ch[x][1],k-sz[ch[x][0]]-cnt[x],root);
            else{
                Splay(x,0,root);
                return val[x];
            }
        }
        int cnt[MAXN*20];
        int val[MAXN*20];
    //---------------------------------------------
    //建立线段树和线段树中的每个结点的平衡树
        struct node
        {
            int l,r,x;
        }mi[MAXN*2];
        void build(int l,int r,int root)
        {
            mi[root].x=99999999;
            mi[root].l=l,mi[root].r=r;
            rt[root]=0;
            for(int i=l;i<=r;i++)
                Insert(rt[root],a[i],0,root);
            if(l>=r)
            {
                mi[root].x=a[r];
                return;
            }
            int m=(l+r)>>1;
            build(lson);
            build(rson);
            mi[root].x=min(mi[root<<1].x,mi[root<<1|1].x);
        }
        void updatemi(int x,int l,int k)
        {
            int L=mi[x].l,R=mi[x].r;
            if(L==R)
            {
                mi[x].x=k;
                return;
            }
            int mid=(L+R)>>1;
            if(l<=mid)
                updatemi(x<<1,l,k);
            else
                updatemi(x<<1|1,l,k);
            mi[x].x=min(mi[x<<1].x,mi[x<<1|1].x);
        }
        int querymi(int x,int l,int r)
        {
            int L=mi[x].l,R=mi[x].r;
            if(l<=L&&R<=r)
                return mi[x].x;
            int mid=(L+R)>>1;
            if(r<=mid)
                return querymi(x<<1,l,r);
            else if(l>mid)
                return querymi(x<<1|1,l,r);
            else
                return min(querymi(x<<1,l,r),querymi(x<<1|1,l,r));
        }
        void update(int l,int r,int root,int i,int x)
        {
            int ans=0;
            findkey(rt[root],a[i],ans);
            Splay(ans,0,root);
            Del(root);
            Insert(rt[root],x,0,root);
    
            if(l>=r)return;
            int m=(l+r)>>1;
            if(i<=m)update(lson,i,x);
            else update(rson,i,x);
        }
        int cntLess(int x,int key)
        {
            int ret=0;
            while(x)
            {
                if(val[x]>key)
                    x=ch[x][0];
                else
                {
                    ret+=cnt[x]+sz[ch[x][0]];
                    x=ch[x][1];
                }
            }
            return ret;
        }
        int getnumLess(int l,int r,int root,int L,int R,int x)
        {
            if(L<=l&&R>=r)
                return cntLess(rt[root],x);
            int m=(l+r)>>1;
            int ret=0;
            if(L<=m)ret+=getnumLess(lson,L,R,x);
            if(R>m)ret+=getnumLess(rson,L,R,x);
            return ret;
        }
        int search(int L,int R,int k)
        {
            int l=0,r=INF;
            int ans=0;
            return getnumLess(1,n,1,L,R,k);
        }
        void solve()
        {
            scanf("%d%d",&n,&m);
            REP(i,1,n)
                scanf("%d",&a[i]);
            build(1,n,1);
            REP(i,1,m)
            {
                int x,y,z;
                char str[4];
                scanf("%s",str);
                if(str[0]=='1')
                {
                    scanf("%d%d",&x,&y);
                    updatemi(1,x,y);
                    update(1,n,1,x,y);
                    a[x]=y;
                }
                else if(str[0]=='2')
                {
                    scanf("%d%d",&x,&y);
                    int k=querymi(1,x,y);
                    int kk=search(x,y,k)-search(x,y,k-1);
                    printf("%d %d
    ",k,kk);
                }
                else
                {
                    scanf("%d%d%d",&x,&y,&z);
                    int k=search(x,y,z);
                    printf("%d
    ",k);
                }
            }
        }
        int a[MAXN];
        int n,m;
    
    }spt;
    int main()
    {
        spt.init();
        spt.solve();
        return 0;
    }
  • 相关阅读:
    DataTable distinct 去重复
    EF 实体字段设置主键和自增
    select into from 和 insert into select 的用法
    EF的 JOIN操作
    Linq左关联 右关联 内关联
    MySQL MGR集群搭建
    论用户体验测试:牛逼的功能千篇一律,好的体验万里挑一
    Spring Cloud使用总结
    数据采集与分析的那些事——从数据埋点到AB测试
    如何能低成本地快速获取大量目标用户,而不是与竞争对手持久战?
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4504648.html
Copyright © 2011-2022 走看看