樹狀數組 線段樹 again- -又不會處理 again- -
看了網上其他人的思路:
就是 要找出最少的分組 分組以數值連續為標準
還是以 右端點 為關鍵點
sum(i)為從 1~i(輸入數下標)的最少分組個數
從左向右 不斷的更新 r(i)
從第一個數開始掃描 當前數a[i]所對應的 i 向上update(i,1)加1
如果 在 i之前 1~i-1中的 數中有 a[i]+1 a[i]-1 則,這兩個數 所在pos[a[i]+1], pos[a[i]-1】分別 向上update(pos,-1) 減1
(其實就是每掃描到一個新的數,在這個數上 加一個組,若之前有和它相鄰的數,則和他相鄰的數的位置要告訴自己和它的boss自己可以歸在最新的那個組,自己和管理它的boss都要減少一組)
邊更新邊計算query的值 即 如果 i==query[].r (query的值 以 r的 非遞減順序儲存)
query的時候 就 用 sum(r)-sum(l)
ok .其實還不是很理解
上code.
#include <iostream>#include <string.h>#include <algorithm>using namespace std;const int MAXN=100010;int n,m,a[MAXN],c[MAXN],pos[MAXN],ans[MAXN];struct node{int l,r,id;}query[MAXN];bool cmp(struct node a,struct node b){return a.r<b.r;}int lowbit(int x){return x&(-x);}void update(int i,int val){while(i<=n){c[i]+=val;i+=lowbit(i);}}int sum(int a,int b){int ar=0,br=0;while(a){ar+=c[a];a-=lowbit(a);}while(b){br+=c[b];b-=lowbit(b);}return (br-ar);}int main(){int T;cin>>T;while(T--){cin>>n>>m;int i,k=1;for (i = 1; i <= n; i++) {cin>>a[i];pos[a[i]]=i;}for(i = 1;i <= m; i++){cin>>query[i].l>>query[i].r;query[i].id=i;}sort(query+1,query+1+m,cmp);for (i = 1; i <= n; i++) {update(a[i],1);if(a[i]<n && pos[a[i]+1]<i) update(pos[a[i]+1],-1);if(a[i]>1 && pos[a[i]-1]<i) update(pos[a[i]-1],-1);while(k<=m && query[k].r==i){ans[query[k].id]=sum(query[k].l,query[k].r);k++;}}for(i = 1; i <= m; ++i){cout<<ans[i]<<endl;}}return 0;}