zoukankan      html  css  js  c++  java
  • 分块 (寻找区间小于k的最大值

    一题简单的分块操作,听说要用set卡就打了下但是感觉貌似不用,好像vector处理也能过。

    题目链接https://loj.ac/problem/6280

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int maxn = 1e5+10;
      5 const int inf = 0x3f3f3f3f;
      6 int dir[10][10] = {{1,0},{-1,0},{0,1},{0,-1}};
      7 int pos[maxn*2], a[maxn*2], lz[maxn*2], minn[maxn];
      8 int l, r, opt, t, n, c, k;
      9 set<int> s[2010];  //用从大到小就是 set<int,greater<int> > s[2010];
     10 
     11 inline int read()
     12 {
     13     char ch = getchar(); ll k = 0, f = 1;
     14     while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
     15     while(ch >= '0' && ch <= '9') {k = (k << 1) + (k << 3) + ch - '0'; ch = getchar();}
     16     return k * f;
     17 }
     18 
     19 inline void reset(int x)
     20 {
     21     s[x].clear();
     22     s[x].insert(a + (x - 1) * t + 1, a + min(x * t, n) + 1);  //更新set
     23 }
     24 
     25 inline void inser(int l, int r, int c)
     26 {
     27     if(pos[l] == pos[r])
     28     {
     29         for(int i = l; i <= r; ++i) a[i] += c;
     30         reset(pos[l]);
     31     }
     32 
     33     else
     34     {
     35         for(int i = l; i <= pos[l] * t; ++i) a[i] += c;
     36         reset(pos[l]);
     37         for(int i = (pos[r] - 1) * t + 1; i <= r; ++i) a[i] += c;
     38         reset(pos[r]);
     39         for(int i = pos[l] + 1; i <= pos[r] - 1; ++i) lz[i] += c;
     40     }
     41 
     42 }
     43 
     44 inline int findy(int l, int r, int c)
     45 {
     46     int ans = -inf;
     47     if(pos[l] == pos[r])
     48     {
     49         for(int i = l; i <= r; ++i)
     50         {
     51             if(lz[pos[l]] + a[i] < c && lz[pos[l]] + a[i] > ans) ans = lz[pos[l]] + a[i];
     52         }
     53 
     54     }
     55 
     56     else
     57     {
     58         for(int i = l; i <= pos[l] * t; ++i) if(lz[pos[l]] + a[i] < c && lz[pos[l]] + a[i] > ans) ans = lz[pos[l]] + a[i];
     59         for(int i = (pos[r] - 1) * t + 1; i <= r; ++i) if(lz[pos[r]] + a[i] < c && lz[pos[r]] + a[i] > ans) ans = lz[pos[r]] + a[i];
     60         for(int i = pos[l] + 1; i <= pos[r] - 1; i++)
     61         {
     62             int x = c - lz[i];
     63             set<int>::iterator it = s[i].lower_bound(x);
     64             if(it == s[i].begin())  continue;   //值得注意的是如果用*lower_bound没找到返回的不一定是0,此时就难判断
     65             it--;
     66             ans = max(ans, *it + lz[i]);
     67         }
     68 
     69     }
     70 
     71     return ans;
     72 }
     73 
     74 int main()
     75 {
     76     n = read();
     77     for(int i = 1; i <= n; ++i) a[i] = read();
     78     t = sqrt(n);
     79 
     80     for(int i = 1; i <= n; ++i)
     81     {
     82         pos[i] = (i - 1)/t + 1;
     83         s[pos[i]].insert(a[i]);
     84     }
     85 
     86     for(int i = 1; i <= n; ++i)
     87     {
     88         opt = read(); l = read(); r = read(); c = read();
     89         if(opt == 0) inser(l, r, c);
     90         else
     91         {
     92             k = findy(l, r, c);
     93             if(k != -inf) cout<<k<<endl;
     94             else cout<<-1<<endl;
     95         }
     96 
     97     }
     98 
     99     return 0;
    100 }

    其中有很多地方代码都可以更加简洁一些,比如维护个L,R数组。但我可能顺着思路写就有点死脑筋,导致检查起来也不太好看。

    用*lower_bound()进行判断容易卡(别问我为什么知道。。

    第一篇随笔,不周到之处见谅

  • 相关阅读:
    23 抽象类 abstract
    22.4 Extends --super 和 this 的区别
    22.3 Extends 构造方法的执行顺序
    22.2 继承的 成员变量的执行顺序
    22.1 Extends 继承的 方法重写@Override 和 方法重载Overload 的区别
    22 Extends 继承(子类、父类)
    21.3代码块考试题
    vue-cli3安装
    ==隐式转换是怎样进行的?
    为什么有时候人们用translate来改变位置而不是定位?
  • 原文地址:https://www.cnblogs.com/a1484755603/p/13407418.html
Copyright © 2011-2022 走看看