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 }
View Code

 

posted @ 2018-10-25 20:15  jack_yyc  阅读(203)  评论(0编辑  收藏  举报