dtoi4699 序列
Posted 1124828077ccj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dtoi4699 序列相关的知识,希望对你有一定的参考价值。
题意:
已知大小为n的一个排列,对于任意一个子序列s,它对ans[k]的贡献为(对于任意的i<|s|,满足s[i]>k>s[i+1]或者s[i]<k<s[i+1]的i的数量)。输出ans[k],k∈[1,n]
题解:
由于个人比较菜,所以我的方法很奇怪。
从小到大枚举i,考虑每一次“点亮”它所在的位置,那么当前的答案就是所有“亮”的位置和“不亮”的位置的贡献。
对于一组合法的(i,j),它对答案的贡献就是2^(n-(j-i+1))。
那么我有一个位置亮了起来,它对答案就会新增暗的地方对它的贡献,所以说我们就用总的贡献减去亮的地方对它的贡献,那么亮的地方对它的贡献可以用线段树维护。大概就是维护一个等比数列,因为等比数列+等比数列还是等比数列,当然比要相等,本题中比只会有2或1/2,所以可以使用线段树维护。
然而本题空间5M(不知道出题人想干啥),于是我就把原本正常的代码各种乱改,以时间换空间甚至是小范围分块大范围快速幂求a^b。然后卡着1s过去了。
#include<cstdio> #include<algorithm> #include<cstdlib> using namespace std; const int mod=1e9+7; int n,a,t[100002],d,ans,cf[30002]; typedef struct{ int sx1,sc1,sx2,sc2; }P; P p[300002]; inline long long ccj(long long x,long long y){ if (x==2 && y<=100000) { int ans=1; if (y<=30000)return cf[y]; while(y>=30000) { ans=(long long)ans*cf[30000]%mod;y-=30000; } ans=(long long)ans*cf[y]%mod; return ans; } int ans=1; while(y) { if (y&1)ans=ans*x%mod; x=x*x%mod;y>>=1; } return ans; } inline void gengxin1(int root,int begin,int end,int begin2,int end2,int sx,bool u){ if (begin>end2 || end<begin2)return; if (begin>=begin2 && end<=end2) { if (u) { p[root].sx1=(p[root].sx1+(long long)sx*ccj(2,begin-begin2)%mod)%mod; } else { p[root].sc1=(p[root].sc1+(long long)sx*ccj(ccj(2,begin-begin2)%mod,mod-2))%mod; } return; } int mid=(begin+end)/2; gengxin1(root*2,begin,mid,begin2,end2,sx,u);gengxin1(root*2+1,mid+1,end,begin2,end2,sx,u); } inline void gengxin2(int root,int begin,int end,int begin2,int end2,int sx,bool u){ if (begin>end2 || end<begin2)return; if (begin>=begin2 && end<=end2) { if (u) { p[root].sx2=(p[root].sx2+(long long)sx*ccj(2,begin-begin2)%mod)%mod; } else { p[root].sc2=(p[root].sc2+(long long)sx*ccj(ccj(2,begin-begin2)%mod,mod-2)%mod)%mod; } return; } int mid=(begin+end)/2; gengxin2(root*2,begin,mid,begin2,end2,sx,u);gengxin2(root*2+1,mid+1,end,begin2,end2,sx,u); } inline void chaxun1(int root,int begin,int end,int wz){ ans=(ans-ccj(2,wz-begin)*p[root].sx1%mod)%mod; ans=(ans-ccj(ccj(2,wz-begin),mod-2)*p[root].sc1%mod)%mod; ans=(ans+mod)%mod; if (begin==end)return; int mid=(begin+end)/2; if (wz<=mid)chaxun1(root*2,begin,mid,wz); else chaxun1(root*2+1,mid+1,end,wz); } inline void chaxun2(int root,int begin,int end,int wz){ ans=(ans-ccj(2,wz-begin)*p[root].sx2%mod)%mod; ans=(ans-ccj(ccj(2,wz-begin),mod-2)*p[root].sc2%mod)%mod; ans=(ans+mod)%mod; if (begin==end)return; int mid=(begin+end)/2; if (wz<=mid)chaxun2(root*2,begin,mid,wz); else chaxun2(root*2+1,mid+1,end,wz); } int main() { scanf("%d",&n);cf[0]=1; for (int i=1;i<=30000;i++)cf[i]=cf[i-1]*2%mod; for (int i=1;i<=n;i++){scanf("%d",&a);t[a]=i;} for (int i=1;i<=n;i++) { chaxun2(1,1,n,t[i]); printf("%lld ",ans);d=0; int t1=ccj(2,n-2),t2=ccj(2,n-t[i]),t3=ccj(2,n-t[i]); if (t[i]<n) { gengxin1(1,1,n,t[i]+1,n,t1,0); gengxin2(1,1,n,t[i]+1,n,t1,0); d=((t1*2%mod-1)-ccj(2,t[i]-1)+1)%mod; d=(d%mod+mod)%mod; } if (t[i]>1) { gengxin1(1,1,n,1,t[i]-1,t3,1); gengxin2(1,1,n,1,t[i]-1,t3,1); d=(d+(t1*2%mod-1)-t2+1)%mod; d=(d%mod+mod)%mod; } ans=(ans+d)%mod;chaxun1(1,1,n,t[i]); } return 0; }
以上是关于dtoi4699 序列的主要内容,如果未能解决你的问题,请参考以下文章