标签:
最近,无聊的过河船同学在玩一种奇怪的名为“小Q的恶作剧”的纸牌游戏。
现在过河船同学手有张牌,分别写着,打乱顺序之后排成一行,位置从左往右按照标号。
接下来小Q同学会给出个操作,分为以下两种:
1.给定,交换从左往右数的第和第张牌,
2.给定,对从左往右数的第张牌,记下位置是这张牌上的数字的牌的数字,询问所有记下的数字加起来的结果。
虽然无聊的过河船同学精通四则运算,但是要完成这么大的计算量还是太辛苦了,希望你能帮他处理这些操作。
第一行是一个正整数,表示测试数据的组数,
对于每组测试数据,
第一行是一个整数,
第二行包含一个的排列,其中第个数表示第张牌上的数字,
第三行是一个整数,表示操作数,
接下来行,每行包含三个整数,其中表示操作的类型。
对于每组测试数据,依次输出所有查询操作的结果,每个结果一行。
1 3 1 2 3 3 2 1 2 1 1 3 2 2 3
3 5
对于样例,
第二次操作后牌上的数字从左往右依次是3,2,1,
第三次操作的结果是位置是第2张牌上的数字的牌的数字加上位置是第3张牌上的数字的牌的数字,也就是第2张牌上的数字加上第1张牌上的数字,结果是5。
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> using namespace std; long long s[100100]; int a[100100],b[100100],flag[100100],t,n,m,Time; int f[10],tot; int lowbit(int x) { return x & (-x); } void update(int x,long long y) { while(x <= n) { s[x] += y; x += lowbit(x); } } long long getsum(int x) { long long tmp = 0; while(x > 0) { tmp += s[x]; x -= lowbit(x); } return tmp; } int main(){ scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i = 1;i <= n;i++) { scanf("%d",&a[i]); b[a[i]] = i; s[i] = 0; } for(int i = 1;i <= n;i++)update(i,a[a[i]]); scanf("%d",&m); for(int i = 1;i <= m;i++) { int op,l,r; scanf("%d%d%d",&op,&l,&r); if(op == 1) { Time++; tot = 2; f[1] = l; f[2] = r; flag[l] = Time; flag[r] = Time; if(flag[b[l]] != Time) { ++tot; f[tot] = b[l]; flag[b[l]] = Time; } if(flag[b[r]] != Time) { ++tot; f[tot] = b[r]; flag[b[r]] = Time; } for(int i = 1;i <= tot;i++) update(f[i],-a[a[f[i]]]); swap(a[l],a[r]); b[a[l]] = l; b[a[r]] = r; for(int i = 1;i <= tot;i++) update(f[i],a[a[f[i]]]); } else printf("%lld\n",getsum(r)-getsum(l-1)); } } return 0; }
标签:
原文地址:http://www.cnblogs.com/chen9510/p/5497458.html