Codeforces 633H. Fibonacci-ish II
题目大意:
一个数列 q次询问 每次询问l r
将数列中l-r的位置排序去重后的数列成为b
输出 sigma b i * F i (其中F i为斐波那契数列中的第i项)
思路:
由于要去重 考虑权值线段树 于是先把整个数列离散
区间+不会=莫队 由于n为30000 考虑每次修改log n的复杂度
用线段树维护当前线段的答案 数字个数
发现并不会维护
因为我们需要把 1-a 1-b 的这两个区间合并为 1- a+b
看了一波tutorial 发现:
(尝试证明 但由于水平太菜只能用通项公式口胡)
这样的话就可以维护了 在线段树内再维护一下那个东西即 答案多项式的系数变为斐波那契前一项
就搞完了
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 30100 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,m,MOD,bl[MAXN],sz,g[MAXN],vis[MAXN],to[MAXN],val[MAXN]; 21 int res[MAXN<<2],tag[MAXN<<2],sum[MAXN<<2],f[MAXN],ans[MAXN]; 22 struct data {int l,r,id;}q[MAXN]; 23 bool cmp(data a,data b) 24 { 25 if(bl[a.l]==bl[b.l]) return a.r<b.r; 26 return a.l<b.l; 27 } 28 inline void upd(int k) 29 { 30 sum[k]=sum[k<<1]+sum[k<<1|1];int lv=sum[k<<1]; 31 res[k]=(res[k<<1]+(f[lv+1]*res[k<<1|1])%MOD+(f[lv]*tag[k<<1|1])%MOD)%MOD; 32 if(lv) tag[k]=(tag[k<<1]+(f[lv]*res[k<<1|1])%MOD+(f[lv-1]*tag[k<<1|1])%MOD)%MOD; 33 else tag[k]=(tag[k<<1]+tag[k<<1|1])%MOD; 34 } 35 void mdf(int k,int l,int r,int x,int w) 36 { 37 if(l==r) {tag[k]=0,sum[k]=w,res[k]=w?g[l]:0;return ;} 38 int mid=l+r>>1; 39 if(x<=mid) mdf(k<<1,l,mid,x,w); 40 else mdf(k<<1|1,mid+1,r,x,w); 41 upd(k); 42 } 43 inline void add(int x) 44 { 45 vis[x]++;if(vis[x]-1) return ; 46 mdf(1,1,n,x,1); 47 } 48 inline void del(int x) 49 { 50 vis[x]--;if(vis[x]) return ; 51 mdf(1,1,n,x,0); 52 } 53 int main() 54 { 55 n=read(),MOD=read(),sz=sqrt(n);int N; 56 for(int i=1;i<=n;i++) val[i]=g[i]=read(),bl[i]=(i-1)/sz,f[i]= i<=2?1:(f[i-1]+f[i-2])%MOD; 57 sort(g+1,g+n+1);N=unique(g+1,g+n+1)-g-1; 58 for(int i=1;i<=n;i++) to[i]=lower_bound(g+1,g+N+1,val[i])-g; 59 m=read(); 60 for(int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i; 61 sort(q+1,q+m+1,cmp);n=N;int l=q[1].l,r=q[1].l-1; 62 for(int i=1;i<=m;i++) 63 { 64 while(l>q[i].l) add(to[--l]); 65 while(l<q[i].l) del(to[l++]); 66 while(r<q[i].r) add(to[++r]); 67 while(r>q[i].r) del(to[r--]); 68 ans[q[i].id]=res[1]; 69 } 70 for(int i=1;i<=m;i++) printf("%d\n",ans[i]); 71 }