日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Squared Permutation(线段树)

發布時間:2023/12/15 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Squared Permutation(线段树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

鏈接:https://ac.nowcoder.com/acm/problem/14113
來源:牛客網

題目描述
最近,無聊的過河船同學在玩一種奇怪的名為“小Q的惡作劇”的紙牌游戲。
現在過河船同學手有n張牌,分別寫著1,2,3,…,n,打亂順序之后排成一行,位置從左往右按照1,2,3,…,n標號。
接下來小Q同學會給出q個操作,分為以下兩種:
1.給定l,r(1 ≤ l<r ≤ n),交換從左往右數的第l和第r張牌,
2.給定l,r(1 ≤ l ≤ r ≤ n),對從左往右數的第i(l ≤ i ≤ r)張牌,記下位置是這張牌上的數字的牌的數字,詢問所有記下的數字加起來的結果。
雖然無聊的過河船同學精通四則運算,但是要完成這么大的計算量還是太辛苦了,希望你能幫他處理這些操作。
輸入描述:
第一行是一個正整數T(≤ 10),表示測試數據的組數,
對于每組測試數據,
第一行是一個整數n(1 ≤ n ≤ 100000),
第二行包含一個1,2,3,…,n的排列,其中第i個數表示第i張牌上的數字,
第三行是一個整數q(0 ≤ q ≤ 100000),表示操作數,
接下來q行,每行包含三個整數op(1 ≤ op ≤ 2),l,r,其中op表示操作的類型。
輸出描述:
對于每組測試數據,依次輸出所有查詢操作的結果,每個結果一行。
示例1
輸入
復制
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。
很扯淡的一道題,卡了很久。
一開始就是單純的把兩個位置的交換過來。但是wa了之后手畫了幾組樣例,發現單純的交換不行,會有后效性,于是手動模擬了幾組樣例,發現除了交換l,r兩個位置上的數字不行,還要交換l和r兩個數字在數組中的位置posl,posr上的數字。自己找的規律,不知道咋證明。路過的大佬指點一波。
代碼如下:

#include<bits/stdc++.h> #define ll long long using namespace std;const int maxx=1e5+100; struct node{int l;int r;ll sum; }p[maxx<<2]; int a[maxx]; int b[maxx]; int n,m;inline void pushup(int cur) {p[cur].sum=p[cur<<1].sum+p[cur<<1|1].sum; } inline void build(int l,int r,int cur) {p[cur].l=l;p[cur].r=r;p[cur].sum=0;if(l==r){p[cur].sum=1ll*a[a[l]];return ;}int mid=l+r>>1;build(l,mid,cur<<1);build(mid+1,r,cur<<1|1);pushup(cur); } inline void update(int pos,int cur) {int L=p[cur].l;int R=p[cur].r;if(L==R){p[cur].sum=1ll*a[a[L]];return ;}int mid=L+R>>1;if(pos<=mid) update(pos,cur<<1);else update(pos,cur<<1|1);pushup(cur); } inline ll query(int l,int r,int cur) {int L=p[cur].l;int R=p[cur].r;if(l<=L&&R<=r) return p[cur].sum;int mid=L+R>>1;if(r<=mid) return query(l,r,cur<<1);else if(l>mid) return query(l,r,cur<<1|1);else return (query(l,mid,cur<<1)+query(mid+1,r,cur<<1|1)); } int main() {int t,op,l,r;scanf("%d",&t);while(t--){scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[a[i]]=i;build(1,n,1);scanf("%d",&m);while(m--){scanf("%d%d%d",&op,&l,&r);if(op==1){int x=a[l];a[l]=a[r];a[r]=x;b[a[r]]=r;b[a[l]]=l;update(l,1);update(r,1);update(b[l],1);update(b[r],1);//b[i]代表著i這個數在數組中的位置。}else if(op==2){printf("%lld\n",query(l,r,1));}}}return 0; }

努力加油a啊,(o)/~

總結

以上是生活随笔為你收集整理的Squared Permutation(线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。