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\n",ask(1,l,r));
            }
        }
    }
}

 

posted @ 2016-04-24 15:59  meekyan  阅读(282)  评论(0编辑  收藏  举报