zoukankan      html  css  js  c++  java
  • bnu 51636 Squared Permutation 线段树

    Squared Permutation

    Time Limit: 6000ms
    Memory Limit: 262144KB
    64-bit integer IO format: %lld      Java class name: Main

    最近,无聊的过河船同学在玩一种奇怪的名为“小Q的恶作剧”的纸牌游戏。

    现在过河船同学手有n张牌,分别写着1,2,3,...,n,打乱顺序之后排成一行,位置从左往右按照1,2,3,...,n标号。

    接下来小Q同学会给出q个操作,分为以下两种:

    1.给定l,r(1 leq l<r leq n),交换从左往右数的第l和第r张牌,

    2.给定l,r(1 leq l leq r leq n),对从左往右数的第i(l leq i leq r)张牌,记下位置是这张牌上的数字的牌的数字,询问所有记下的数字加起来的结果。

    虽然无聊的过河船同学精通四则运算,但是要完成这么大的计算量还是太辛苦了,希望你能帮他处理这些操作。

     

    Input

    第一行是一个正整数T(leq 10),表示测试数据的组数,

    对于每组测试数据,

    第一行是一个整数n(1 leq n leq 100000)

    第二行包含一个1,2,3,...,n的排列,其中第i个数表示第i张牌上的数字,

    第三行是一个整数q(0 leq q leq 100000),表示操作数,

    接下来q行,每行包含三个整数op(1 leq op leq 2),l,r,其中op表示操作的类型。

     

    Output

    对于每组测试数据,依次输出所有查询操作的结果,每个结果一行。

     

    Sample Input

    1
    3
    1 2 3
    3
    2 1 2
    1 1 3
    2 2 3

    Sample Output

    3
    5

    Hint

    对于样例,

    第二次操作后牌上的数字从左往右依次是3,2,1,

    第三次操作的结果是位置是第2张牌上的数字的牌的数字加上位置是第3张牌上的数字的牌的数字,也就是第2张牌上的数字加上第1张牌上的数字,结果是5。

     

    Source

    思路:很显然用线段树,但是发现线段树在更新两点会有后效;
       最多更新四个点;注意的是先更新flag数组;
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    using namespace std;
    #define ll long long
    #define mod 1000000007
    #define inf 999999999
    int scan()
    {
        int res = 0 , ch ;
        while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) )
        {
            if( ch == EOF ) return 1 << 30 ;
        }
        res = ch - '0' ;
        while( ( ch = getchar() ) >= '0' && ch <= '9' )
            res = res * 10 + ( ch - '0' ) ;
        return res ;
    }
    //#pragma comment(linker, "/STACK:102400000,102400000")
    ll a[100010],flag[100010];
    struct is
    {
        ll l,r;
        ll sum;
    }tree[100010*5];
    void buildtree(ll l,ll r,ll pos)
    {
        tree[pos].l=l;
        tree[pos].r=r;
        if(l==r)
        {
            tree[pos].sum=a[a[l]];
            return;
        }
        ll mid=(l+r)/2;
        buildtree(l,mid,pos*2);
        buildtree(mid+1,r,pos*2+1);
        tree[pos].sum=tree[pos*2].sum+tree[pos*2+1].sum;
    }
    void update(ll point,ll change,ll pos)
    {
        if(tree[pos].l==point&&tree[pos].r==point)
        {
            tree[pos].sum=change;
            return;
        }
        ll mid=(tree[pos].l+tree[pos].r)/2;
        if(point<=mid)
        update(point,change,pos*2);
        else
        update(point,change,pos*2+1);
        tree[pos].sum=tree[pos*2].sum+tree[pos*2+1].sum;
    }
    ll query(ll l,ll r,ll pos)
    {
        if(tree[pos].l==l&&tree[pos].r==r)
        {
            return tree[pos].sum;
        }
        ll mid=(tree[pos].l+tree[pos].r)/2;
        if(mid>=r)
        return query(l,r,pos*2);
        else if(mid<l)
        return query(l,r,pos*2+1);
        else
        return query(l,mid,pos*2)+query(mid+1,r,pos*2+1);
    }
    int main()
    {
        ll x,y,z,i,t;
        int gg;
        scanf("%d",&gg);
        while(gg--)
        {
            scanf("%lld",&x);
            for(i=1;i<=x;i++)
            {
                scanf("%lld",&a[i]);
                flag[a[i]]=i;
            }
            buildtree(1,x,1);
            scanf("%lld",&y);
            while(y--)
            {
                ll op,l,r;
                scanf("%lld%lld%lld",&op,&l,&r);
                if(op==1)
                {
                    ll hh=query(l,l,1);
                    ll kk=query(r,r,1);
                    ll hhh=query(flag[l],flag[l],1);
                    ll kkk=query(flag[r],flag[r],1);
                    update(l,kk,1);
                    update(r,hh,1);
                    flag[a[l]]=r;
                    flag[a[r]]=l;
                    update(flag[l],kkk,1);
                    update(flag[r],hhh,1);
                    swap(a[l],a[r]);
                    /*for(i=1;i<=x;i++)
                    cout<<a[i]<<" ";
                    cout<<endl;
                    for(i=1;i<=x;i++)
                    cout<<flag[i]<<" ";
                    cout<<endl;
                    for(i=1;i<=x;i++)
                    cout<<query(i,i,1)<<" ";
                    cout<<endl;*/
                }
                else
                {
                    printf("%lld
    ",query(l,r,1));
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Leetcode 16.25 LRU缓存 哈希表与双向链表的组合
    Leetcode437 路径总和 III 双递归与前缀和
    leetcode 0404 二叉树检查平衡性 DFS
    Leetcode 1219 黄金矿工 暴力回溯
    Leetcode1218 最长定差子序列 哈希表优化DP
    Leetcode 91 解码方法
    Leetcode 129 求根到叶子节点数字之和 DFS优化
    Leetcode 125 验证回文串 双指针
    Docker安装Mysql记录
    vmware虚拟机---Liunx配置静态IP
  • 原文地址:https://www.cnblogs.com/jhz033/p/5427844.html
Copyright © 2011-2022 走看看