zoukankan      html  css  js  c++  java
  • TJU 3758. Jewel 【划分树,树状数组】

    http://acm.tju.edu.cn/toj/showp3758.html
    TJU 3758.   Jewel
    模拟题,开始数组为空,有以下操作:
    Insert x
        Put a bead with size x to the right of the chain (0 < x < 231, and x is different from all the sizes of beads currently in the chain)

    Query_1 s t k
        Query the k-th smallest bead between position s and t, inclusive. You can assume 1 ≤ s ≤ t ≤ L, (L is the length of the current chain), and 1 ≤ k ≤ min (100, t - s + 1)

    Query_2 x
        Query the rank of the bead with size x, if we sort all the current beads by ascent order of sizes. The result should between 1 and L (L is the length of the current chain)


    Query_3 k
        Query the size of the k-th smallest bead currently (1 ≤ k ≤ L, L is the length of the current chain)

    要求统计每种问题的答案

    分析:对于问题1和3可用划分树解决,对于问题2用树状数组解决,注意用树状数组前需要对数据离散化

    View Code
    #include<stdio.h>
    #include
    <algorithm>
    #include
    <iostream>
    using namespace std;
    typedef
    long long LL;
    struct Q//问题
    {
    int kind;//问题类型
    int x,k;
    int s,t;
    int ans;
    }q[
    35000*4+10];
    const int MAXN = 100000+10;
    int tree[22][MAXN],toleft[22][MAXN];
    int sorted[MAXN];//已经排好序的数据
    int c[MAXN];
    inline
    int low(int x)
    {
    return (x&(-x));
    }
    void add(int x, int n)
    {
    while( x <= n)
    {
    c[x]
    ++;
    x
    += low(x);
    }
    }
    LL Sum(
    int x)
    {
    LL ans
    = 0;
    while(x > 0)
    {
    ans
    += c[x];
    x
    -= low(x);
    }
    return ans;
    }

    void build_tree(int left,int right,int deep)//建树
    {
    if(left==right)return;
    int mid = (left+right)>>1;
    int i;
    int same = mid-left+1;//位于左子树的数据
    for(i=left;i<=right;i++) //计算放于左子树中与中位数相等的数字个数
    {
    if(tree[deep][i]<sorted[mid])
    same
    --;
    }

    int ls = left;
    int rs = mid+1;
    for(i=left;i<=right;i++)
    {
    int flag = 0;
    if((tree[deep][i]<sorted[mid])||(tree[deep][i]==sorted[mid]&&same>0))
    {
    flag
    = 1;
    tree[deep
    +1][ls++] = tree[deep][i];
    if(tree[deep][i]==sorted[mid])same--;
    }
    else
    {
    tree[deep
    +1][rs++] = tree[deep][i];
    }

    toleft[deep][i]
    =toleft[deep][i-1]+flag;
    }

    build_tree(left,mid,deep
    +1);
    build_tree(mid
    +1,right,deep+1);
    }

    int query(int left,int right,int k,int L,int R,int deep)
    {
    if(left==right)return tree[deep][left];
    int mid = (L+R)>>1;
    int x = toleft[deep][left-1]-toleft[deep][L-1];//位于left左边的放于左子树中的数字个数
    int y = toleft[deep][right] - toleft[deep][L-1];//到right为止位于左子树的个数
    int ry = right-L-y;//到right右边为止位于右子树的数字个数
    int cnt = y-x;//[left,right]区间内放到左子树中的个数
    int rx = left-L-x;//left左边放在右子树中的数字个数
    if(cnt>=k)
    return query(L+x,L+y-1,k,L,mid,deep+1);
    else
    return query(mid+rx+1,mid+1+ry,k-cnt,mid+1,R,deep+1);

    }

    int find(int x,int left,int right)
    {
    int ans = 0;
    while(left<=right)
    {
    int mid = (left+right)>>1;
    if(x==sorted[mid])return mid;
    if(x<sorted[mid])
    right
    =mid-1;
    else
    left
    =mid+1;
    }
    return ans;
    }
    int main()
    {
    int op = 0;
    int cases = 0;
    while(scanf("%d",&op)!=EOF)
    {
    cases
    ++;
    int n = 1;
    int qnum = 0;//问题个数

    while(op--)
    {
    char str[20];
    scanf(
    "%s",str);
    if(str[0]=='I')
    {
    scanf(
    "%d",&sorted[n]);
    tree[
    0][n]=sorted[n];
    n
    ++;
    }
    else
    {
    int len = strlen(str);
    if(str[len-1]=='1')
    {
    q[qnum].kind
    = 1;
    scanf(
    "%d%d%d",&q[qnum].s,&q[qnum].t,&q[qnum].k);
    qnum
    ++;
    }
    else
    if(str[len-1]=='2')
    {
    q[qnum].kind
    = 2;
    scanf(
    "%d",&q[qnum].x);
    q[qnum].t
    = n-1;
    qnum
    ++;
    }
    else
    if(str[len-1]=='3')
    {
    q[qnum].kind
    = 3;
    scanf(
    "%d",&q[qnum].k);
    q[qnum].s
    =1;
    q[qnum].t
    = n-1;
    qnum
    ++;
    }
    }
    }
    sort(sorted
    +1,sorted+n);
    memset(c,
    0,sizeof(c));
    int i,pre = 1;
    build_tree(
    1,n-1,0);
    LL sum1
    =0,sum2=0,sum3=0;
    for(i=0;i<qnum;i++)
    {
    if(q[i].kind==1)
    {
    //query(int left,int right,int k,int L,int R,int deep)
    sum1+=query(q[i].s,q[i].t,q[i].k,1,n-1,0);

    }
    else
    if(q[i].kind==3)
    {
    sum3
    +=query(q[i].s,q[i].t,q[i].k,1,n-1,0);
    }
    else
    {
    for(;pre<=q[i].t;pre++)
    {
    int index = find(tree[0][pre],1,n-1);
    add(index,n
    -1);
    }
    int index=find(q[i].x,1,n-1);
    //printf("%ld\n",Sum(index));
    sum2+=Sum(index);
    }
    }
    printf(
    "Case %d:\n",cases);
    cout
    <<sum1<<endl;
    cout
    <<sum2<<endl;
    cout
    <<sum3<<endl;
    // printf("%I64d\n%I64d\n%I64d\n",sum1,sum2,sum3);
    }
    return 0;
    }
  • 相关阅读:
    水晶报表参数字段在代码中赋值
    存储过程编写经验和优化措施
    积分与排名
    大话处理器
    抽象数学
    开普勒:天空的立法者
    Scalable Face Image Retrieval with IdentityBased Quantization and Multireference Reranking
    配色辞典
    图像识别顶级赛事
    Information Geometry
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/1971809.html
Copyright © 2011-2022 走看看