zoukankan      html  css  js  c++  java
  • 倍增从入门到入土

    入门

    P1081 [NOIP2012 提高组] 开车旅行

    tj前:看到第一第二大,可以倍增维护,但是这建边也太恶心了,然后对于第一问我在挨个点跑一边?倍增起码有个区间吧,宁给我个 (x_0) 我也不知道该从那么跑哇,只能从头往后排,这不曼斯?
    比值可以模拟,但是这该怎么跑

    tj后:看了看可以模拟,我先试试
    70分暴力模拟

    /*
        c1[i] 距离i最近的城市
        c2[i] 距离i次进的城市 
        dis1[i] 从i到c[i]的距离
        dis2[i] 同理 次二进的 
        A---2
        B---1+ 
    */
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <bits/stdc++.h>
    #include <algorithm>
    #define int long long
    using namespace std;
    
    const int A = 1e7+10;
    const int B = 1e6+10;
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
      char c = getchar();
      int x = 0, f = 1;
      for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
      for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
      return x * f;
    }
    
    int n,m,h[B],xl,p;
    
    int dis1[B],dis2[B],c1[B],c2[B];
    
    double minv=INT_MAX;
    
    main()
    {
        int x,y;
        n=read();
        for (int i=1;i<=n;i++) h[i]=read();
        
        for (int i=n-1;i>=1;i--)
        {
            int minx=i+1,minxx=0;
            dis1[i]=abs(h[i]-h[i+1]);
            for (int j=i+2;j<=n;j++)
            {
                if (dis1[i]>abs(h[i]-h[j]) || (dis1[i]==abs(h[i]-h[j]) && h[j]<h[minx]))
                {
                    minxx=minx;
                    minx=j;
                    dis2[i]=dis1[i];
                    dis1[i]=abs(h[i]-h[j]); 
                }
                else if (dis2[i]==0 || dis2[i]>abs(h[i]-h[j]) || (dis2[i]==abs(h[i]-h[j]) && h[j]<h[minxx]))
                {
                    minxx=j;
                    dis2[i]=abs(h[i]-h[j]);
                }
            }
            c1[i]=minx;
            c2[i]=minxx;
        }
        
        xl=read();
        int ans=0;
        for (int i=1;i<=n;i++)
        {
            int js=0,sum=0,a=0,b=0;
            int s=i;
            while (1)
            {
                
                if(!js)
                {
                    if (a+b+dis2[s]>xl || !c2[s]) break;
                    a+=dis2[s];
                    s=c2[s];
                }
                else
                {
                    if (a+b+dis1[s]>xl || !c1[s]) break;
                    b+=dis1[s];
                    s=c1[s];
                }
                js^=1;
            } 
            if (!ans || 1.0*a / b - minv < -0.00000001 || (fabs(1.0*a / b - minv) <= 0.00000001&&h[ans] < h[i]))
            {
                minv = 1.0*a / b;
                ans = i;
            }
        }
        
        printf("%lld
    ",ans);
        p=read();
        while (p--)
        {
            int w,js=0,a=0,b=0;
            x=read(),y=read();
            int s=x;
            while (1)
            {
                if(!js)
                  {
                    if (a+b+dis2[s]>y || !c2[s]) break;
                    a+=dis2[s];
                    s=c2[s];
                }
                else
                {
                    if (a+b+dis1[s]>y || !c1[s]) break;
                    b+=dis1[s];
                    s=c1[s];
                }
                js^=1;
            }
            printf("%lld %lld
    ",a,b);
        } 
        return 0;
    } 
    
    

    倍增优化,双向链表初始化
    做完我都在想今天晚上我为甚选择的宁,一晚上没了

    /*
        c1[i] 距离i最近的城市
        c2[i] 距离i次进的城市 
        dis1[i] 从i到c[i]的距离
        dis2[i] 同理 次二进的 
        A---2
        B---1+ 
    */
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <bits/stdc++.h>
    #include <algorithm>
    #define int long long
    using namespace std;
    
    const int A = 1e7+10;
    const int B = 1e6+10;
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
      char c = getchar();
      int x = 0, f = 1;
      for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
      for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
      return x * f;
    }
    
    int n,m,h[B],xl,p;
    
    int pos[B],dis1[B],dis2[B],c1[B],c2[B];
    int  c3[B][21],dist3[B][21], dist4[B][21], dist5[B][21];
    
    double minv=INT_MAX;
    
    struct node{int h,bh,last,next;}q[B];
    
    bool cmp(node a,node b){return a.h<b.h;}
    
    void updata(int i,int loc,int x)
    {
        if (x>=1 && x<=n)
            {
                if (!dis1[i] || dis1[i]>abs(q[loc].h -q[x].h) || (dis1[i]==abs(q[loc].h -q[x].h) && q[x].h <q[pos[c1[i]]].h))
                {
                    c2[i]=c1[i];
                    c1[i]=q[x].bh;
                    dis2[i]=dis1[i];
                    dis1[i]=abs(q[loc].h -q[x].h); 
                }
                else if (dis2[i]==0 || dis2[i]>abs(q[loc].h -q[x].h) || (dis2[i]==abs(q[loc].h -q[x].h) && q[x].h <q[pos[c2[i]]].h))
                {
                    c2[i]=q[x].bh;
                    dis2[i]=abs(q[loc].h -q[x].h);
                }
            }
    }
    
    main()
    {
        int x,y;
        n=read();
        for (int i=1;i<=n;i++) q[i].h=read(),q[i].bh=i;
        sort(q+1,q+1+n,cmp);
        
        for (int i=1;i<=n;i++)
        {
            pos[q[i].bh]=i;
            if (i!=1) q[i].last=i-1;
            if (i!=n) q[i].next=i+1;
        }
        
        for (int i=1;i<=n;i++)
        {
            int loc = pos[i];
            updata(i, loc, q[q[loc].last].last);
            updata(i, loc, q[loc].last);
            updata(i, loc, q[loc].next);
            updata(i, loc, q[q[loc].next].next);
            if (q[loc].last)q[q[loc].last].next = q[loc].next;
            if (q[loc].next)q[q[loc].next].last = q[loc].last;
            q[loc].last = q[loc].next = 0;
        }
        
         for ( int i = 1; i <= n; ++i)
        {
            dist4[i][0] = dis2[i];
            dist5[i][0] = dis1[c2[i]];
            dist3[i][0] = dis2[i] + dis1[c2[i]];
            c3[i][0] = c1[c2[i]];
        }
        
        for ( int j = 1; j <= 20; ++j)
            for ( int i = 1; i <= n; ++i)
            {
                c3[i][j] = c3[c3[i][j - 1]][j - 1];
                if (c3[i][j])
                {
                    dist3[i][j] = dist3[i][j - 1] + dist3[c3[i][j - 1]][j - 1];
                    dist4[i][j] = dist4[i][j - 1] + dist4[c3[i][j - 1]][j - 1];
                    dist5[i][j] = dist5[i][j - 1] + dist5[c3[i][j - 1]][j - 1];
                }
            }
        int xx = read(), ans = 0;
        for (int i = 1; i <= n; ++i)
        {
             int a = 0, b = 0, loc = i, x0 = xx;
            for ( int j = 20; j >= 0; --j)
            {
                if (dist3[loc][j] && x0 >= dist3[loc][j])
                {
                    x0 -= dist3[loc][j];
                    a += dist4[loc][j];
                    b += dist5[loc][j];
                    loc = c3[loc][j];
                }
            }
            if (dis2[loc] <= x0)a += dis2[loc];
            if (a <= 0)continue;
            if (!ans || 1.0*a / b - minv < -0.00000001 || (fabs(1.0*a / b - minv) <= 0.00000001&&q[pos[ans]].h < q[pos[i]].h))
            {
                minv = 1.0*a / b;
                ans = i;
            }
        }
        
        printf("%lld
    ",ans);
        p=read();
        while (p--)
        {
             int s = read(), x = read(), a = 0, b = 0;
            for ( int j = 20; j >= 0; --j)
            {
                if (dist3[s][j] && x >= dist3[s][j])
                {
                    x -= dist3[s][j];
                    a += dist4[s][j];
                    b += dist5[s][j];
                    s = c3[s][j];
                }
            }
            if (dis2[s] <= x)a += dis2[s];
            printf("%lld %lld
    ", a, b);
        } 
        return 0;
    } 
    
    
  • 相关阅读:
    全文搜索 Contains 与like 的区别
    Easyui _treegrid 动态加载子节点
    十五、ES开启SSL访问
    十二、ES分词器
    十一、ES监控
    十六、源码部署EFK之快乐没有了
    十四、ES开启密码认证
    十三、ES备份恢复
    十七、优化ES
    正则表达式
  • 原文地址:https://www.cnblogs.com/lToZvTe/p/14525936.html
Copyright © 2011-2022 走看看