• Appleman and a Sheet of Paper


    题意:

    给一纸条,两种操作:

      1.将左侧长度为$x$的纸条向右翻折。

      2.询问位于$[l,r]$的纸条总长度。

    解法:

    考虑启发式,每一次一个小纸条折叠我们可以看做是一次合并,如果我们每一次将较小的纸条并入较大的纸条。

    这样对于每一个数字,包含它的纸条长度每次至少乘以2,这样每一个数字变动$logn$次。

    对于一个$2x > len$过大的操作,我们可以转化为将右面的$len-x$个翻折过来,并执行一次翻转操作。

    用$rev$记录是否翻转,分类讨论即可。

    同时用线段树记录区间和。

    这样总效率$O(nlog^2n)$

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 
     5 #define N 100010
     6 #define lb(x) ((x)&(-x))
     7 
     8 using namespace std;
     9 
    10 int n,q,L,R;
    11 int sumv[N],a[N];
    12 
    13 void add(int x,int v)
    14 {
    15     for(int i=x;i<=n&&i;i+=lb(i))
    16         sumv[i]+=v;
    17 }
    18 
    19 int ask(int x)
    20 {
    21     int ans=0;
    22     for(int i=x;i>0;i-=lb(i)) ans+=sumv[i];
    23     return ans;
    24 }
    25 
    26 void solve(int cnt,int typ)
    27 {
    28     if(typ==0)
    29     {
    30         for(int i=0;i<cnt;i++)
    31         {
    32             a[L+cnt+i] += a[L+cnt-i-1];
    33             add(L+cnt+i,a[L+cnt-i-1]);
    34             add(L+cnt-i-1,-a[L+cnt-i-1]);
    35             a[L+cnt-i-1]=0;
    36         }
    37         L+=cnt;
    38     }
    39     else
    40     {
    41         for(int i=0;i<cnt;i++)
    42         {
    43             a[R-cnt-i] += a[R-cnt+i+1];
    44             add(R-cnt-i,a[R-cnt+i+1]);
    45             add(R-cnt+i+1,-a[R-cnt+i+1]);
    46             a[R-cnt+i+1]=0;
    47         }
    48         R-=cnt;
    49     }
    50 }
    51 
    52 int main()
    53 {
    54     while(~scanf("%d%d",&n,&q))
    55     { 
    56         for(int i=1;i<=n;i++) sumv[i]=0,a[i]=1;
    57         for(int i=1;i<=n;i++) add(i,1);
    58         L=1;
    59         R=n;
    60         int rev=0;
    61         for(int i=1,cmd,x,y;i<=q;i++)
    62         {
    63             scanf("%d%d",&cmd,&x);
    64             if(cmd==1)
    65             {
    66                 int len = R-L+1;
    67                 if(x*2<=len) solve(x,rev);
    68                 else solve(len-x,rev^1),rev^=1;
    69             }
    70             else
    71             {
    72                 int ans;
    73                 scanf("%d",&y);
    74                 if(!rev) ans = ask(L+y-1)-ask(L+x-1);
    75                 else ans = ask(R-x)-ask(R-y);
    76                 printf("%d
    ",ans);
    77             }
    78         }
    79     }
    80 }
    View Code
  • 相关阅读:
    csu 1141 节能
    WA:ZOJ 1025 Wooden Sticks
    UVa 531 Compromise
    UVa 437 The Tower of Babylon
    UVa 10285 Longest Run on a Snowboard
    在asp.net使用web.config身份验证
    掌握 Ajax,第 6 部分: 建立基于 DOM 的 Web 应用程序
    面向对象编程思想
    一步一步学Remoting之五:异步操作
    Asp.net 2.0 用 FileUpload 控件实现多文件上传 用户控件(示例代码下载)
  • 原文地址:https://www.cnblogs.com/lawyer/p/6650590.html
Copyright © 2020-2023  润新知