洛谷P4155.国旗计划

洛谷P4155.国旗计划

  • 贪心 + 倍增

    • 对于每一个i来说,要找最优解需要尽可能选择最远的战士
    • 枚举的复杂度是无法接受的,因此可以采用倍增优化
    • 令f[i,j]为第i个战士往右(断环成链) 选择2j个战士(不一定是距离2j)到达的战士编号
    • f[i,j] = f[f[i,j-1][j-1];
    • 在搜索时采用先大跳后小跳的策略(同LCA),此时ans += 2i
  •   #include<iostream>
      #include<cstdio>
      #include<algorithm>
      using namespace std;
      const int N= 2e5+5;
      
      int n,m;
      int ans[N];
      struct node{
          int id,l,r;
      }s[N*2];
      int cmp(node a,node b)
      {
          return a.l < b.l;
      }
      int f[N*2][20];
      
      void pre()
      {
          //对于每一个i,找到尽可能远的第一个战士编号
          for(int i=1,p=i;i<=2*n;i++)
          {
              while(p <= 2*n && s[p].l <= s[i].r)
                  p++;
              f[i][0] = p - 1;
          }
          //f的递推表达式
          for(int i=1;i<20;i++)
              for(int j=1;j<=2*n;j++)
                  f[j][i] = f[f[j][i-1]][i-1];
      }
      
      void solve(int k)
      {
          //定上限l + m,res初始化为1(自身),
          int lim = s[k].l + m,res = 1,p = k;
          //从大到小遍历
          for(int i=19;i>=0;i--)
          {
              //如果能跳,并且lim不取等(最后差一点不跳了,存入res + 1)
              if(f[k][i] != 0 && s[f[k][i]].r < lim)
              {
                  res += (1 << i);
                  k = f[k][i];
              }
          }
          ans[s[p].id] = res + 1;
      }
      
      int main()
      {
          cin>>n>>m;
          for(int i=1;i<=n;i++)
          {
              cin>>s[i].l>>s[i].r;
              if(s[i].r < s[i].l)
                  s[i].r += m;
              s[i].id = i;
          }
          sort(s+1,s+n+1,cmp);
          //断环成链
          for(int i=1;i<=n;i++)
          {
              s[i+n] = s[i];
              s[i+n].l = s[i].l + m;
              s[i+n].r = s[i].r + m;
          }
          pre();
          for(int i=1;i<=n;i++)
              solve(i);
          for(int i=1;i<=n;i++)
              cout<<ans[i]<<" ";
      }
    
"c洛谷国旗"是一个题目,在洛谷在线评测系统上。该题目的要求是给定一个由N×M个小方块组成的棋盘布,每个方块是白色、蓝色或红色。你需要按照某国法律规定的国旗规则,将布涂成合法的国旗。根据法律规定,国旗的布局应该是从最上方若干行(至少一行)的格子全部是白色的,接下来若干行(至少一行)的格子全部是蓝色的,剩下的行(至少一行)全部是红色的。你需要通过对格子上颜色的涂改来实现这个目标。具体来说,你需要在一些格子上涂上新的颜色来盖住之前的颜色。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [洛谷 P3392 涂国旗](https://blog.csdn.net/m0_60777643/article/details/122149321)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [洛谷-P3392 涂国旗](https://blog.csdn.net/weixin_43098069/article/details/107484242)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光男孩01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值