HDU5320 : Fan Li

考虑枚举左端点i,则随着右端点的右移,一共只有$O(\log n)$种不同的gcd取值。所以首先通过ST表+二分查找预处理出$O(n\log n)$个四元组(x,i,l,r),表示左端点为i,右端点取值范围在[l,r]内,且这一段的gcd都为x。

将四元组按照x为第一关键字,i为第二关键字排序,对于相同的x一起处理。

当x相同时,显然所有的i互不相同。设f[i]为恰好以位置i为结尾的最优解,则对于一个四元组(x,i,l,r),能更新它的最优解为区间[1,i-1]的最优值+1,然后用它更新区间[l,r]的f[]。用支持打标记的线段树维护即可。时间复杂度$O(n\log^2n)$。

比赛的时候TLE不止,赛后什么都没改交了一发居然直接就过了。

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=100010,K=17,P=998244353,M=262145;
int T,n,m,i,j,x,y,l,r,mid,Log[N],val,f[K][N];
struct PI{
  int x,i,l,r;
  PI(){}
  PI(int _x,int _i,int _l,int _r){x=_x,i=_i,l=_l,r=_r;}
}a[3000000];
inline bool cmp(PI a,PI b){return a.x==b.x?a.i<b.i:a.x<b.x;}
struct Num{
  int x,y;
  Num(){x=y=0;}
  Num(int _x,int _y){x=_x,y=_y;}
  inline Num operator+(Num b){
    if(x<b.x)return b;
    if(x>b.x)return Num(x,y);
    return Num(x,(y+b.y)%P);
  }
  inline Num operator+(int _x){return Num(x+_x,y);}
  inline Num operator-(int b){return Num(x,(long long)y*b%P);}
  inline void operator+=(Num b){*this=*this+b;}
}tmp,v[M],tag[M],ans;
int pos[M];
inline void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10LL)+=c-‘0‘;}
inline int askgcd(int y){int k=Log[y-i+1];return __gcd(f[k][i],f[k][y-(1<<k)+1]);}
inline void clean(int x){
  if(pos[x]<T)pos[x]=T,v[x]=tag[x]=Num();
}
inline void tag1(int x,Num y){
  clean(x);
  v[x]+=y;
  tag[x]+=y;
}
inline void pb(int x){
  if(tag[x].x){
    tag1(x<<1,tag[x]);
    tag1(x<<1|1,tag[x]);
    tag[x]=Num();
  }
}
inline void up(int x){
  clean(x<<1),clean(x<<1|1);
  v[x]=v[x<<1]+v[x<<1|1];
}
void change(int x,int a,int b,int c,int d){
  clean(x);
  if(c<=a&&b<=d){tag1(x,tmp);return;}
  pb(x);
  int mid=(a+b)>>1;
  if(c<=mid)change(x<<1,a,mid,c,d);
  if(d>mid)change(x<<1|1,mid+1,b,c,d);
  up(x);
}
void ask(int x,int a,int b,int c,int d){
  clean(x);
  if(c<=a&&b<=d){tmp+=v[x];return;}
  pb(x);
  int mid=(a+b)>>1;
  if(c<=mid)ask(x<<1,a,mid,c,d);
  if(d>mid)ask(x<<1|1,mid+1,b,c,d);
  up(x);
}
int main(){
  for(i=2;i<=100000;i++)Log[i]=Log[i>>1]+1;
  while(~scanf("%d",&n)){
    m=0;
    ans=Num();
    for(i=1;i<=n;i++)read(f[0][i]);
    int flag=0;
    for(i=2;i<=n;i++)if(f[0][i]!=f[0][i-1]){flag=1;break;}
    if(!flag){printf("%d 1\n",n);continue;}
    for(j=1;j<K;j++)for(i=1;i+(1<<j-1)<=n;i++)f[j][i]=__gcd(f[j-1][i],f[j-1][i+(1<<j-1)]);
    for(i=1;i<=n;i++)for(x=i;x<=n;x=y+1){
      val=askgcd(y=x),l=x+1,r=n;
      while(l<=r)if(askgcd(mid=(l+r)>>1)==val)l=(y=mid)+1;else r=mid-1;
      a[++m]=PI(val,i,x,y);
    }
    sort(a+1,a+m+1,cmp);
    for(i=1;i<=m;i++){
      if(i==1||a[i].x!=a[i-1].x)T++;
      tmp=Num();
      if(a[i].i>1)ask(1,1,n,1,a[i].i-1);
      if(!tmp.x)tmp=Num(1,1);else tmp.x++;
      ans+=tmp-(a[i].r-a[i].l+1);
      change(1,1,n,a[i].l,a[i].r);
    }
    printf("%d %d\n",ans.x,ans.y);
  }
  return 0;
}

  

时间: 2024-11-05 22:34:16

HDU5320 : Fan Li的相关文章

百度搜索研发部:同义词反馈机制

1.   介绍 由于搜索算法本身的局限性,对于用户的语义.意图等理解不够,而基于用户行为的点击调权,作为对传统搜索算法的补充,在搜索中扮演着重要的作用.尽管用户行为已经被证明在搜索中的效果,但是一直只是停留在query-url层面,或者ngram-url层面[1],没有深入反馈到检索算法中的基础策略,比如:同义词.紧密度.省略等,这些策略影响了url与query之间的关系.本文以对同义词的反馈为例,提出一个通用的基于用户行为的基础策略反馈框架. 由于同义词词典与线上应用算法的限制,检索系统中存在

初探Neo4J中的Cypher

由于RDF数据库需要,需要调研图形数据库,选择了Neo4J进行尝试,发现它包含了一个名为"Cypher"的操作语言,使用了一下感觉非常不错,所有有写点东西的必要. 从官网上盗个图: 其实,这个图也就标识了cypher语言的基本功能,节点a到节点b,关系是LIKES,其操作的方法与sql的select一样选择符合某种条件的实体,由此强烈建议大家使用网页版进行熟悉操作,比较直观,可以直接得到图形. 闲话少说,我们姑且成上面的为万能公式,该万能公式大体上分为两个部分()与[],其中()表示某

Vanets Routing paper reading

1.A VANET Routing based on the Real-timeRoad Vehicle Density in the City Environment, Hyun Yu , Joon Yoo , Sanghyun Ahn. ICUFN 2013. 在这个VANET路由协议中,每辆车利用beacon信息和road imformation table计算某条路上的实时车辆密度信息.基于实时的车辆密度信息,每辆车都能建立起用于包发送的可靠路由.具体地说,每辆车都会周期性地发送beac

2015.07.28 (3)

做多校被虐成狗了---什么都不会啊-- 还是觉得把能够想懂一点的,不管是看的别人的题解或者代码的,还是看的标程的,都记录一下-- 加油------ 1001  Magician 1002  RGCDQ 先筛素数,然后记录 prime[1] = 2; prime[2] = 3; prime[3] = 5; prime[4] = 7; prime[5]=11; 记录下这个是为了计算cnt[]数组,cnt[i]表示i由几种素数构成 再算pre[i][j]表示的是前i个数,f(i) = j的数的个数 然

js li内容a-z排序和搜索 拼音

1.遍历所有li 把li中的中文转换成拼音和拼音首字母缩写 2.声明一个26个长度的二维数组.把26个英文字母 (("a").charCodeAt(0)) - 97; 0索引就是a,1就是b 以此类推. 3.把li自身的html 放到 二维数组中. 4.清空ul 循环二维数组,从 a-z 放把保存的html到lu中 5.查询,文本框注册 keyup 事件.判断输入内容 中是否 在拼音,拼音缩写,中文名称 是否存在.存在显示,不存在隐藏.为空显示所有 html <div class

js计算li不换行的情况下,ul的宽度--用于做有滚动的导航条

var lenght_li=0; $('.info_tab li').each(function(){ lenght_li+=$(this).outerWidth(true); }); $('.info_tab').css({ 'width':lenght_li+1 });

js点击图片删除子标签li

上图的效果图请看下面 点击图片部分会删除子标签li部分

$(&#39;div&#39;,&#39;li&#39;)

要搞清楚$('div','li') 和 $('div , li') 和 $('div  li') 区别$('div','li')是$(子,父),是从父节点里找子,而不是找li外面的div $('div , li')才是找所有的div和li,之间不存在父子关系 $('div li') 是找div里面所有li,包括子级,孙子级,总之就是div里面所有li,不管有几层关系 $('div','li')

如何处理 在html中 li 的高度自适应(且li里面的内容有浮动的情况下)

废话不多说,我们写贴出代码 这个是 Html 代码 <div class="main"> <ul> <li> <div class="main-left">23</div> <div class="main-right"> <p>text1</p> <p>text2</p> </div> </li> &l