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

    Squared Permutation

    最近,无聊的过河船同学在玩一种奇怪的名为“小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

    题解:

      明显的线段树

      不过要注意的是在交换的的时候,可能影响的位置有4个,多更新就好了

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include<map>
    #include<queue>
    using namespace std;
    const int N = 4e6+10, M = 30005, mod = 1e9 + 7, INF = 1e9+1000;
    typedef long long ll;
    
    int n,vis[N],a[N];
    int tr[N],l[N],r[N],las[N];
    ll  sum[N];
    void build(int k,int x,int y) {
        l[k] = x;
        r[k] = y;
        if(x==y) {
            sum[k]=a[a[x]];return ;
        }
        int mid = (x+y)>>1;
        build(k<<1,x,mid);
        build(k<<1|1,mid+1,y);
        sum[k] = sum[k<<1]+sum[k<<1|1];
    }
    void update(int k,int x,int c) {
        if(x==l[k]&&x==r[k]) {
            sum[k] = c;
            return ;
        }
        int mid = (l[k]+r[k])/2;
        if(x<=mid) update(k<<1,x,c);
        else update(k<<1|1,x,c);
        sum[k] = sum[k<<1]+sum[k<<1|1];
    }
    ll ask(int k,int s,int t) {
        if(l[k]==s&&t==r[k]) return sum[k];
        int mid = (l[k]+r[k])>>1 ;
        ll ret = 0;
        if(t<=mid) ret = ask(k<<1,s,t);
        else if(s>mid) ret = ask(k<<1|1,s,t);
        else ret = ask(k<<1,s,mid)+ask(k<<1|1,mid+1,t);
        return ret;
    }
    
    int main() {
        int T;
        scanf("%d",&T);
        while(T--) {
            scanf("%d",&n);
            for(int i=1;i<=n;i++) {
                scanf("%d",&a[i]);
                las[a[i]] = i;
            }
            build(1,1,n);
            int q;
            scanf("%d",&q);
            while(q--) {
                int op,l,r;
                scanf("%d%d%d",&op,&l,&r);
                if(op == 1) {
                    int t1 = a[r];
                    int t2 = a[l];
                    swap(a[l],a[r]);
                    update(1,l,a[t1]);
                    update(1,r,a[t2]);
                    las[a[l]] = l;
                    las[a[r]] = r;
                    update(1,las[l],a[l]);
                    update(1,las[r],a[r]);
                }
                else {
                    printf("%lld
    ",ask(1,l,r));
                }
            }
        }
    }
  • 相关阅读:
    有关Lucene的问题(7):用Lucene构建实时的索引
    Lucene学习总结之九:Lucene的查询对象(1)
    有关Lucene的问题(6):Lucene的事务性
    Lucene学习总结之九:Lucene的查询对象
    面向连接的Socket Server的简单实现
    Lucene 原理与代码分析完整版
    有关Lucene的问题(8):用Lucene构建实时索引的文档更新问题
    k8spod的状态为evicted的情况分析
    centos7环境 的 k8s安装helm 3.7.1
    VMware虚拟机中CentOS7的硬盘空间扩容
  • 原文地址:https://www.cnblogs.com/zxhl/p/5427248.html
Copyright © 2011-2022 走看看