题目链接:Problem - 4638
做了两天莫队和分块,留个模板吧。
当插入r的时候,设arr[r]代表r的位置的数字,判断vis[arr[r-1]]和vis[arr[r+1]]是否访问过,如果两个都访问过,那么块的个数-1,如果有一个访问过,块的个数不变,如果都为0,块的个数+1.
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 const int maxn = 1e5+50; 8 int vis[maxn]; 9 struct node 10 { 11 int l,r; 12 int block; 13 int id; 14 }; 15 node q[maxn]; 16 int arr[maxn]; 17 bool cmp(node A,node B) 18 { 19 if(A.block==B.block) return A.r<B.r; 20 return A.l<B.l; 21 } 22 int res[maxn]; 23 int query(int l,int r) 24 { 25 if(vis[l]==1&&vis[r]==1) return -1; 26 if((vis[l]==1&&vis[r]==0)||(vis[l]==0&&vis[r]==1)) return 0; 27 if(vis[l]==0&&vis[r]==0) return 1; 28 } 29 int main() 30 { 31 int T;cin>>T; 32 while(T--) 33 { 34 int n,m; 35 scanf("%d %d",&n,&m); 36 int block = sqrt(n); 37 for(int i=1;i<=n;i++) scanf("%d",&arr[i]); 38 memset(vis,0,sizeof(vis)); 39 for(int i=1;i<=m;i++) 40 { 41 scanf("%d %d",&q[i].l,&q[i].r); 42 q[i].block = q[i].l/block; 43 q[i].id = i; 44 } 45 sort(q+1,q+m+1,cmp); 46 int l=1,r=0; 47 int ans = 0; 48 for(int i=1;i<=m;i++) 49 { 50 while(r < q[i].r) 51 { 52 r++; 53 vis[arr[r]] = 1; 54 ans += query(arr[r]-1,arr[r]+1); 55 } 56 while(r > q[i].r) 57 { 58 ans -= query(arr[r]-1,arr[r]+1); 59 vis[arr[r]] = 0; 60 r--; 61 } 62 while(l < q[i].l) 63 { 64 ans -= query(arr[l]-1,arr[l]+1); 65 vis[arr[l]] = 0; 66 l++; 67 } 68 while(l > q[i].l) 69 { 70 l--; 71 vis[arr[l]] = 1; 72 ans += query(arr[l]-1,arr[l]+1); 73 } 74 res[q[i].id] = ans; 75 } 76 for(int i=1;i<=m;i++) 77 { 78 printf("%d\n",res[i]); 79 } 80 } 81 return 0; 82 }
时间: 2024-10-13 12:29:47