• GDOI2014 吃(D1T3) 线段树


    Description

    W师兄计划了很久,终于成功的在BG开了一家寿司店。

    正当W师兄还在兴奋的时候,这时一个噩耗传来,吃货L师姐居然知道了这件事,而且正赶过来,W师兄瞬间心就冷了下去,但是机智的W师兄也瞬间想到了应付L师姐的策略.......

    这时,L师姐到了寿司店,先四处望了望风景,发现现在只有L师姐一个顾客,下面是L师姐的选餐说明:

    1.寿司店内的寿司被排在一行共N个盘子里,按从左到右编号为1~N。

    2.每个位置上寿司的数量是确定的并且有玻璃窗保护。

    3.每隔一段时间就会有一个选餐时间,L师姐可以在一个连续的区间[l, r]中选择其中一盘,然后在该区间之外选择另一盘(如果区间外有盘子)。

    L师姐发现这家寿司店厨师的制作速度很快,总能在下一次选餐时间前将寿司数量恢复原样。

    作为有尊严有追求的吃货,L师姐也有自己的规则,L师姐在选完两盘寿司后,会决定每口恰好吃D个寿司,且使得两盘寿司刚好可以分别吃完,不剩余任何寿司。比如两盘寿司数量为2和4,那么D=1或者D=2都可以恰好将两盘寿司分别吃干净,而两盘寿司数量为3和5时,那么只能D=1才行。

    作为有特殊追求的L师姐才不在乎吃的数量,L师姐在乎的是一口吃多个寿司的感觉。于是,如果L师姐可以一口吃D个寿司,那么L师姐的愉悦值为D,但是L师姐没有选到两盘寿司,那么她的愉悦值为0。

    现在L师姐知道每个盘子所放着的寿司数量,L师姐想知道每次选择时间过后她可以获得的最大愉悦值是多少?

     
     

    Input

    第一行输入一个整数N,表示寿司的盘子数量。

    第二行输入N个整数a1,a2,…,aN,ai表示第i个盘子内的寿司数量。

    第三行输入一个整数M,表示有多少个选餐时间。

    接下来M行,每行两个整数li, ri (1 <= li <= ri <= N),含义如题面所示。

    Output

    输出M行,第i行表示第i个选择时间师姐可能达到的最大愉悦值D。
     

    Sample Input

    输入1:

    5

    1 2 3 4 5

    2

    2 3

    2 4

    输入2:

    5

    2 4 8 16 32

    2

    3 4

    2 3

    Sample Output

    输出1:

    2

    1

    输出2:

    16

    8

    样例解释:

    样例1里的第一个选餐时间,可以选择2和4,这样L师姐就可以每次吃两个寿司,使得两个盘子都可以吃干净,第二个选餐时间,师姐不管选哪两个盘子,都只能每次吃一个。

    样例2 里的第一个选餐时间,可以选择16和32,而第二个选餐时间,L师姐可以选择8和16或者8和32。
     

    Data Constraint

    对于20%的数据,N <= 100, M <= 100, max(a1,a2,…,aN) <= 100。

    对于50%的数据,N <= 10000, M <= 10000, max(a1,a2,…,aN) <= 10000。

    对于100%的数据,N <= 100000, M <= 100000, max(a1,a2,…,aN) <= 100000。
     

    用pre[][i][j]记录每个数离a[i]最近的(前/后)含有它的第j个因子的数。然后把询问排序离线处理,用线段树f[i]记录在范围之前/之后的数中与i的最大gcd

    正着做一次统计(1-l-1,l-r)的maxgcd,反着做一次统计(l-r,r+1-n)的maxgcd即可

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    
    using namespace std;
    
    int f[800111];
    int pre[2][100111][101],can[100111][101];
    int hash[100111];
    int n,m,tot,i,j,k,last;
    int ans[100111],a[100111];
    
    struct data{
        int l,r,id;
    }q[100111];
    
    bool cmp(data a,data b)
    {
        return a.l<b.l;
    }
    
    bool cmp2(data a,data b)
    {
        return a.r>b.r;
    }
    
    void insert(int l,int r,int x,int y,int t)
    {
        int mid;
        if(l==r){
            f[t]=max(f[t],y);
            return;
        }
        mid=(l+r)/2;
        if(x<=mid)insert(l,mid,x,y,t+t);
        if(x>mid)insert(mid+1,r,x,y,t+t+1);
        f[t]=max(f[t+t],f[t+t+1]);
    }
    
    int ask(int l,int r,int x,int y,int t)
    {
        int mid;
        if(l==x&&r==y)return f[t];
        mid=(l+r)/2;
        if(y<=mid)return ask(l,mid,x,y,t+t);
        if(x>mid)return ask(mid+1,r,x,y,t+t+1);
        if(x<=mid&&y>mid)return max(ask(l,mid,x,mid,t+t),ask(mid+1,r,mid+1,y,t+t+1));
    }
    
    int main()
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)scanf("%d",&a[i]);
        memset(hash,0,sizeof(hash));
        for(i=1;i<=n;i++){
            tot=0;
            for(j=1;j<=(int)sqrt(a[i]);j++)if(a[i]%j==0){
                tot++;
                pre[0][i][tot]=hash[j];
                can[i][tot]=j;
                hash[j]=i;
                k=a[i]/j;
                if(j!=k){
                    tot++;
                    can[i][tot]=k;
                    pre[0][i][tot]=hash[k];
                    hash[k]=i;
                }
            }
            can[i][0]=tot;
        }
        memset(hash,0,sizeof(hash));
        for(i=n;i>=1;i--){
            tot=0;
            for(j=1;j<=(int)sqrt(a[i]);j++)if(a[i]%j==0){
                tot++;
                can[i][tot]=j;
                pre[1][i][tot]=hash[j];
                hash[j]=i;
                k=a[i]/j;
                if(k!=j){
                    tot++;
                    can[i][tot]=k;
                    pre[1][i][tot]=hash[k];
                    hash[k]=i;
                }
            }
            can[i][0]=tot;
        }
        scanf("%d",&m);
        for(i=1;i<=m;i++){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id=i;
        }
        sort(q+1,q+1+m,cmp);
        last=1;
        memset(f,0,sizeof(f));
        for(i=1;i<=m;i++){
            for(j=last;j<q[i].l;j++)
                for(k=1;k<=can[j][0];k++)if(pre[1][j][k])insert(1,n,pre[1][j][k],can[j][k],1);
            ans[q[i].id]=ask(1,n,q[i].l,q[i].r,1);
            last=q[i].l;
        }
        memset(f,0,sizeof(f));
        sort(q+1,q+1+m,cmp2);
        last=n;
        for(i=1;i<=m;i++){
            for(j=last;j>q[i].r;j--)
                for(k=1;k<=can[j][0];k++)if(pre[0][j][k])insert(1,n,pre[0][j][k],can[j][k],1);
            ans[q[i].id]=max(ans[q[i].id],ask(1,n,q[i].l,q[i].r,1));
            last=q[i].r;
        }
        for(i=1;i<=m;i++)printf("%d
    ",ans[i]);
    }
  • 相关阅读:
    说一下AOP和IOC的实现原理
    sql 2005 express版本如果安装vs 2010则被sql 2008 express升级代替
    北京热死了
    Webservices,remoting,WCF比较一下
    CGI(拾遗)
    士农工商
    外网无法访问iis服务器
    好好整理了一下胡子
    用IIS在本机虚拟一个域名发布站点(小技巧)
    给目前自己开发的分布式系统做个定义
  • 原文地址:https://www.cnblogs.com/applejxt/p/3993211.html
Copyright © 2020-2023  润新知