HDU5320 Fan Li
来源:互联网 发布:唱歌伴奏软件 编辑:程序博客网 时间:2024/05/06 14:36
传送门
题目大意
给定
题解
注意到元素范围是一个
如果一个区间右端点固定,那么在左端点往左移的时候区间的
而区间
于是可以枚举右端点,二分左端点预处理出
然后枚举
假设正在计算
将
这个可以用树状数组维护前缀最大值来搞.
然而比较麻烦的是方案数的统计.
对于那些
i<l ,对sum[R] 的贡献是:sum[i]⋅(r−l+1) .l≤i<r ,对sum[R] 的贡献是:sum[i]⋅(r−i) .
这里又出现了两个维度,一个是下标一个是dp值….要是得再来个二维数据结构我可受不了…..
注意到随着
所以对于有值的
于是我们可以二分找到满足
其实还有很多可以优化的地方,像我这样做复杂度已经爆炸了.
所以我也懒得算总的复杂度了.
代码
#include<cstdio>#include<cstring>#include<algorithm>#define lowbit(x) (x&-x)using namespace std;const int N=1e5+5,LG_N=18,S=2333335,LG_S=23,mod=998244353;int n,dp[N],lg[N],ST[N][LG_N],bit_mx[N],bit_sum[2][N];struct UNIT{ int R,l,r,val; inline bool operator <(const UNIT &tmp)const{ if(val!=tmp.val)return val<tmp.val; return R<tmp.R; }}arr[N*LG_S];void init(){ memset(dp,0,sizeof dp); memset(bit_mx,0,sizeof bit_mx); memset(bit_sum,0,sizeof bit_sum); for(int i=2,j=1;i<N;++i){ lg[i]=j; if(!(i&(i-1)))++j; }}void rd(int &res){ res=0; char c; while(c=getchar(),c<48); do res=(res<<3)+(res<<1)+(c^48); while(c=getchar(),c>47);}int gcd(int a,int b){ return b?gcd(b,a%b):a;}int query_gcd(int L,int R){ int k=lg[R-L+2]-1; return gcd(ST[L][k],ST[R-(1<<k)+1][k]);}inline void Max(int &a,int b){ if(b>a)a=b;}inline void Min(int &a,int b){ if(b<a)a=b;}int query_mx(int x){ int res=0; while(x){ Max(res,bit_mx[x]); x&=x-1; } return res;}void update_mx(int x,int val){ while(x<=n){ Max(bit_mx[x],val); x+=lowbit(x); }}inline void mod_add(int &a,int b){ if((a+=b)>=mod)a-=mod;}int query_sum(bool type,int x){ int res=0; while(x){ mod_add(res,bit_sum[type][x]); x&=x-1; } return res;}int query_itv_sum(bool type,int L,int R){ int res=query_sum(type,R)-query_sum(type,L-1); if(res<0)res+=mod; return res;}void update_sum(bool type,int x,int val){ while(x<=n){ mod_add(bit_sum[type][x],val); x+=lowbit(x); }}void solve(){ for(int i=1;i<=n;++i) rd(ST[i][0]); for(int j=1;1<<j<=n;++j) for(int i=1;i+(1<<j)-1<=n;++i) ST[i][j]=gcd(ST[i][j-1],ST[i+(1<<j-1)][j-1]); int tot=0; for(int R=1;R<=n;++R){ int r=R; while(r){ int val=query_gcd(r,R), bin_L=1,bin_R=r,l; while(bin_L<=bin_R){ int mid=bin_L+bin_R>>1; if(query_gcd(mid,R)==val){ l=mid; bin_R=mid-1; } else bin_L=mid+1; } arr[tot++]=(UNIT){R,l,r,val}; r=l-1; } } sort(arr,arr+tot); int ans=0,ans_sum; for(int i=0,j;i<tot;){ for(j=i;j==i||j<tot&&arr[j].val==arr[j-1].val;++j){ int R=arr[j].R,l=arr[j].l,r=arr[j].r,sum=0, pre_L,pre_R,bin_L,bin_R; dp[R]=query_mx(r-1)+1; if(dp[R]>1){ bin_L=i; bin_R=j-1; while(bin_L<=bin_R){ int mid=bin_L+bin_R>>1; if(dp[arr[mid].R]+1==dp[R]){ pre_L=mid; bin_R=mid-1; } else if(dp[arr[mid].R]+1>dp[R])bin_R=mid-1; else bin_L=mid+1; } bin_L=pre_L; bin_R=j-1; while(bin_L<=bin_R){ int mid=bin_L+bin_R>>1; if(dp[arr[mid].R]+1==dp[R]){ pre_R=mid; bin_L=mid+1; } else bin_R=mid-1; } pre_L=arr[pre_L].R; pre_R=arr[pre_R].R; if(pre_L<l){ sum=1ll*query_itv_sum(0,pre_L,min(l-1,pre_R))*(r-l+1)%mod; } Max(pre_L,l); Min(pre_R,r-1); if(pre_L<=pre_R){ sum=(sum+1ll*query_itv_sum(0,pre_L,pre_R)*r-query_itv_sum(1,pre_L,pre_R))%mod; if(sum<0)sum+=mod; } } else sum=r-l+1; if(dp[R]>ans){ ans=dp[R]; ans_sum=sum; } else if(dp[R]==ans){ mod_add(ans_sum,sum); } update_mx(R,dp[R]); update_sum(0,R,sum); update_sum(1,R,1ll*sum*R%mod); } for(;i<j;++i){ int x=arr[i].R; dp[x]=0; while(x<=n){ bit_mx[x]=bit_sum[0][x]=bit_sum[1][x]=0; x+=lowbit(x); } } } printf("%d %d\n",ans,ans_sum);}int main(){ init(); while(~scanf("%d",&n))solve(); return 0;}/* Jun.22.16 Tags:dp,bit Submissions:2 Memory(KB) 44856 Time(ms) 2152 Length(Bytes) 3381*/
0 0
- HDU5320 Fan Li
- HDU 5320 Fan Li
- 【HDU】5320 Fan Li【线段树】
- li
- li
- li
- li
- fan.exe
- kernel fan
- hao fan
- fan error
- fan qiang
- fan xing
- Google Fan专用鞋
- 听说过anti-fan吗
- one opensource fan
- osx 下,fan qiang
- fan out flow
- leetcode--Longest Common Prefix
- linux命令行汇集
- 定位
- android之View坐标系
- 一、性能测试基础知识
- HDU5320 Fan Li
- Makefile
- 6.22java集合
- PagerAdapter
- 完美版 竖直的SeekBar
- Hive体系结构
- Linux使用笔记 (一) 虚拟机运行CentOS7
- 【写高科技的文章】:如何写高科技的文章
- 单线程解析文件,根据文件关键词进行统计,并将结果输出(三)