莫队算法
莫队算法是对暴力的一种优雅诠释,以根号n分块然后进行排序分类 (莫队很简单 ,但这个例题被我做炸了)
莫队先将给的数据分块,然后将每次询问的顺序记录下来 也就是node.id 最后再输出
不得不说 莫队这个操作直接优化根号n实在是太强
https://codeforces.com/problemset/problem/617/E
题目大意:求在每次询问中,区间内异或和等于3的组数
可能是对异或和接触比较少 ,一上来看到题就傻了,后来才想起来异或和的基操,在这里面都用到了
a[ i , j ] = a [ 0 , i ] ^ a [ 0 , j ]
附上ac代码
#include<string.h> #include<algorithm> #include<iostream> #include<math.h> using namespace std; typedef long long ll; const int maxn=1<<20; int n,m,k; ll pos[maxn]; //pos是指分的哪一块 int a[maxn]; //数组a前缀和 记录前n项的异或和 ll Ans=0; int L=1,R=0; ll flag[maxn],ans[maxn]; //flag就是总和 ans是结果 struct node { int l,r,id; }Q[maxn]; bool cmp(node a,node b) { if(pos[a.l]==pos[b.l]) return a.r<b.r; else return pos[a.l]<pos[b.l]; } void add(int x) { Ans+=flag[a[x]^k]; // 我死都想不出来qwq flag[a[x]]++; } void del(int x) { flag[a[x]]--; Ans-=flag[a[x]^k]; //注意顺序 } int main() { scanf("%d%d%d",&n,&m,&k); int sz=sqrt(n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); a[i]^=a[i-1]; pos[i]=i/sz; } for(int i=1;i<=m;i++) { scanf("%d%d",&Q[i].l,&Q[i].r); Q[i].id=i; } flag[0]=1; sort(Q+1,Q+1+m,cmp); for(int i=1;i<=m;i++) { while(L<Q[i].l) { del(L-1); //对于异或操作还是太不了解 看能不能补一补 L++; } while(L>Q[i].l) { L--; // add(L-1); } while(R<Q[i].r) { R++; add(R); } while(R>Q[i].r) { del(R); R--; } ans[Q[i].id]=Ans; } for(int i=1;i<=m;i++) printf("%I64d\n",ans[i]); return 0; }
https://vjudge.net/problem/SPOJ-DQUERY
模板题 记录所问区间中有多少种颜色
Example
Input 5 1 1 2 1 3 3 1 5 2 4 3 5 Output 3 2 3
#include<string.h> #include<algorithm> #include<iostream> #include<math.h> using namespace std; typedef long long ll; const int maxn=300010; int cnt[1000010]; int R=0,L=1,Ans=0; int a[maxn],ans[maxn],pos[maxn]; struct node { int l,r,id; }q[maxn]; bool cmp(node a,node b) { if(pos[a.l]==pos[b.l]) return a.r<b.r; return pos[a.l]<pos[b.l]; } void del(int x) //改这里 { cnt[a[x]]--; if(cnt[a[x]]==0) Ans--; } void add(ll x) //改这里 { if(cnt[a[x]]==0) Ans++; cnt[a[x]]++; } void mo(int i) { while(L>q[i].l) { add(--L); } while(L<q[i].l) { del(L++); } while(R>q[i].r) { del(R--); } while(R<q[i].r) { add(++R); } ans[q[i].id]=Ans; } int main() { int n,t; scanf("%d",&n); int len=sqrt(n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } scanf("%d",&t); for(int i=1;i<=t;i++) { scanf("%d%d",&q[i].l,&q[i].r); pos[i]=i/len; //分块 q[i].id=i; } sort(q+1,q+1+t,cmp); //分块排序 for(int i=1;i<=t;i++) { mo(i); } for(int i=1;i<=t;i++) printf("%d\n",ans[i]); return 0; }
吾志所向
一往无前
愈挫愈奋
再接再励
——卓

浙公网安备 33010602011771号