【CF633H】Fibonacci-ish II 莫队+线段树
【CF633H】Fibonacci-ish II
题意:给你一个长度为n的序列ai。m个询问,每个询问形如l,r:将[l,r]中的所有ai排序并去重,设得到的新数列为bi,求b1F1+b2F2+...(Fi是斐波那契数)。
n,m≤30000,ai≤109
题解:比较好想,但细节很难处理的题(我根本不懂斐波那契数列~)。
显然只能用莫队。我们对权值开一棵线段树,那么新加入一个数时,我们要进行的是:单点修改,区间整体换成下一个斐波那契数。如果你懒的话直接上矩乘就完事了,如果你还想知道矩阵的每一项到底是什么数的话,自己手推递推式就好了。区间整体换成上一个斐波那契数呢?手动求个逆就行了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | #include <cstring> #include <cstdio> #include <iostream> #include <algorithm> #define lson x<<1 #define rson x<<1|1 using namespace std; const int maxn=30010; int n,m,N,Q,B; int f[maxn],g[maxn],p[maxn],ref[maxn],cnt[maxn],v[maxn],ans[maxn]; struct node { int l,r,org; }q[maxn]; int s[maxn<<2][2],siz[maxn<<2],tag[maxn<<2]; bool cmp2( const node &a, const node &b) { return (a.l/B==b.l/B)?(a.r<b.r):(a.l/B<b.l/B); } bool cmp1( const int &a, const int &b) { return v[a]<v[b]; } inline void upd( int x, int y) { tag[x]+=y; if (y>0) { int a=s[x][0],b=s[x][1]; s[x][0]=(f[y+1]*a+f[y]*b)%m,s[x][1]=(f[y]*a+f[y-1]*b)%m; } else { int a=s[x][0],b=s[x][1]; y=-y; s[x][0]=(g[y-1]*a+g[y]*b)%m,s[x][1]=(g[y]*a+g[y+1]*b)%m; } } void updata( int l, int r, int x, int a, int b, int y) { siz[x]+=y; if (l==r) { if (y==-1) s[x][0]=s[x][1]=0; else s[x][0]=f[b]*ref[l]%m,s[x][1]=f[b-1]*ref[l]%m; return ; } if (tag[x]) upd(lson,tag[x]),upd(rson,tag[x]),tag[x]=0; int mid=(l+r)>>1; if (a<=mid) updata(l,mid,lson,a,b,y),upd(rson,y); else updata(mid+1,r,rson,a,b+siz[lson],y); s[x][0]=(s[lson][0]+s[rson][0])%m,s[x][1]=(s[lson][1]+s[rson][1])%m; } inline void add( int x) { if (!cnt[x]) updata(1,N,1,x,1,1); cnt[x]++; } inline void del( int x) { cnt[x]--; if (!cnt[x]) updata(1,N,1,x,0,-1); } inline int rd() { int ret=0,f=1; char gc= getchar (); while (gc< '0' ||gc> '9' ) { if (gc== '-' ) f=-f; gc= getchar ();} while (gc>= '0' &&gc<= '9' ) ret=ret*10+(gc^ '0' ),gc= getchar (); return ret*f; } int main() { n=rd(),m=rd(),B=500; int i,l,r; for (i=1;i<=n;i++) v[i]=rd(),p[i]=i; sort(p+1,p+n+1,cmp1); for (i=1;i<=n;i++) { if (i==1||v[p[i]]!=ref[N]) ref[++N]=v[p[i]]; v[p[i]]=N; } for (i=1;i<=N;i++) ref[i]%=m; f[1]=1,g[1]=1; for (i=2;i<=n+1;i++) f[i]=(f[i-1]+f[i-2])%m,g[i]=(g[i-2]-g[i-1])%m; Q=rd(); for (i=1;i<=Q;i++) q[i].l=rd(),q[i].r=rd(),q[i].org=i; sort(q+1,q+Q+1,cmp2); for (l=1,r=0,i=1;i<=Q;i++) { while (l>q[i].l) add(v[--l]); while (l<q[i].l) del(v[l++]); while (r<q[i].r) add(v[++r]); while (r>q[i].r) del(v[r--]); ans[q[i].org]=(s[1][0]+m)%m; } for (i=1;i<=Q;i++) printf ( "%d\n" ,ans[i]); return 0; } //3 1000 1 2 3 3 1 1 3 3 1 3 |
| 欢迎来原网站坐坐! >原文链接<
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步