1. 程式人生 > >bnu 51636 Squared Permutation(樹狀陣列)(北師16校賽)

bnu 51636 Squared Permutation(樹狀陣列)(北師16校賽)

最近,無聊的過河船同學在玩一種奇怪的名為“小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

Author

quailty

題目大意:

有一個1到n的排列組成的的數列ai,有m次詢問,詢問有兩種操作,1.交換a[l],a[r],2.求以a[l]...到a[r]這些數為下標的a中數的和。

解題思路:

               樹狀陣列i的位置維護以a[i]為下標a中的數(即a[a[i]]),這樣一來就是每次2詢問求和都是連續的區間,那麼在1詢問的時候就更新樹狀陣列:

               第一步:把a中的數當作指向自己陣列中數的指標,更新指向l,r的數字在樹狀陣列中的值(如果指向lr本身就指向l或者r那就不需要改,以免和下面重複)

               第二步:把a[l],a[r]交換之後更新樹狀陣列中的l和r為新的a[a[l]],a[a[r]].

              2詢問的時候直接輸出sum[l]-sum[i-1]即可,因為之前定義樹狀陣列的意義的時候已經可以保證這樣一點

#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#define C(a) memset(a,0,sizeof a)
#define C_1(a) memset(a,-1,sizeof a)
#define C_I(a) memset(a,0x3f,sizeof a)
typedef long long ll;
using namespace std;
const int maxn = 1e6 + 20;
ll a[maxn], n, bit[maxn];
void add(int x, int y)
{
	while (x <= n)
	{
		a[x] += y;
		x += x&-x;
	}
}
ll sum(int x)
{
	ll s = 0;
	while (x > 0)
	{
		s += a[x];
		x -= x&-x;
	}
	return s;
}
void init()
{
	C(a);
	C(bit);
}
int num[maxn];
int ma[maxn];
int main()
{
	int T; cin >> T;
	while (T--)
	{
		scanf("%lld", &n);
		init();
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &num[i]);
			ma[num[i]] = i;
		}
		for (int i = 1; i <= n; i++)
		{
			bit[i] = num[num[i]];
			add(i, num[num[i]]);
		}
		int q;
		scanf("%d", &q);
		int type, r, l;
		while (q--)
		{
			scanf("%d%d%d", &type, &l, &r);
			if (type == 1)
			{
				if (ma[l] != l&&ma[l] != r)
				{
					add(ma[l], -num[l]);
					add(ma[l], num[r]);
				}
				if (ma[r] != r&&ma[r] != l)
				{
					add(ma[r], -num[r]);
					add(ma[r], num[l]);
				}
				add(r, -num[num[r]]);
				add(l, -num[num[l]]);
				swap(num[l], num[r]);
				add(l, num[num[l]]);
				add(r, num[num[r]]);
				ma[num[r]] = r;
				ma[num[l]] = l;
			}
			else
			{
				printf("%lld\n", sum(r) - sum(l - 1));
			}
		}
	}
	return 0;
}