image.png
前缀和跟差分是逆运算

例题

POJ3061 Subsequence

  1. #include<iostream>
  2. #include<cstring>
  3. using namespace std;
  4. const int maxn = 1e5+100;
  5. int prefix[maxn],input[maxn];
  6. int main(){
  7. int t;
  8. cin >> t;
  9. while(t--){
  10. memset(prefix,0,sizeof prefix);
  11. memset(input,0,sizeof input);
  12. int n,s,res = maxn;
  13. cin >> n >> s;
  14. for(int i=1;i<=n;i++){
  15. cin >> input[i];
  16. prefix[i] = prefix[i-1]+input[i];
  17. }
  18. int i=0,j = 1;
  19. while(j<=n){
  20. if(prefix[j]-prefix[i]<s) j++;
  21. else{
  22. while(prefix[j]-prefix[i]>=s) i++;
  23. res = min(res,j-i+1);
  24. }
  25. }
  26. if(res!=maxn) cout << res << endl;
  27. else cout << "0" << endl;
  28. }
  29. return 0;
  30. }

NC16561 国王的游戏

image.png

  1. #include<iostream>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<vector>
  5. using namespace std;
  6. const int maxn = 1e5;
  7. struct node{
  8. int x,y;
  9. }arr[maxn];
  10. bool cmp(node a,node b){
  11. return a.x*a.y < b.x*b.y;
  12. }
  13. vector<int> mul(vector<int>a, int b){ // 高精度乘法
  14. vector<int> res;
  15. int t = 0;
  16. for(int i=0;i<a.size();i++){
  17. t += a[i]*b;
  18. res.push_back(t%10);
  19. t /=10;
  20. }
  21. while(t){
  22. res.push_back(t%10);
  23. t/=10;
  24. }
  25. return res;
  26. }
  27. vector<int> div(vector<int>a, int b){ // 高精度除法
  28. vector<int> res;
  29. int t = 0;
  30. for(int i=a.size()-1;i>=0;i--){
  31. t = t*10+a[i];
  32. int x = t/b;
  33. res.push_back(x);
  34. t %= b;
  35. }
  36. reverse(res.begin(),res.end());
  37. while(res.size()>1&&!res.back()) res.pop_back(); // 去除前导0
  38. return res;
  39. }
  40. vector<int> max_vector(vector<int> a, vector<int> b){ // 比较大小
  41. if(a.size()>b.size()) return a;
  42. if(a.size()<b.size()) return b;
  43. if(vector<int>(a.rbegin(),a.rend())>vector<int>(b.rbegin(),b.rend()))
  44. return a;
  45. else
  46. return b;
  47. }
  48. int main(){
  49. int n;
  50. cin >> n;
  51. for(int i=0;i<=n;i++){
  52. cin >> arr[i].x >> arr[i].y;
  53. }
  54. sort(arr+1,arr+n+1,cmp);
  55. vector<int> res(1,0), a(1,1);
  56. for(int i=0;i<=n;i++){
  57. if(i) res = max_vector(res,div(a,arr[i].y));
  58. a = mul(a,arr[i].x);
  59. }
  60. for(int i=res.size()-1;i>=0;i--){
  61. cout << res[i];
  62. }
  63. cout << endl;
  64. return 0;
  65. }

NC16649 校门外的树

L1.1 枚举(尺取法、前缀和、差分等)、贪心 - 图3和 M1.1 枚举(尺取法、前缀和、差分等)、贪心 - 图4版本
直接模拟,时间复杂度:1.1 枚举(尺取法、前缀和、差分等)、贪心 - 图5

#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 1e5+10;
int f[maxn];
int main(){
    int L,M,x,y,res=0;
    cin >> L >> M;
    while(M--){
        cin >> x >> y;
        for(int i=x;i<=y;i++){
            f[i]=1;
        }
    } 
    for(int i=0;i<=L;i++){
        res += (f[i]==0);
    }
    cout << res << endl;
    return 0;
}

1.1 枚举(尺取法、前缀和、差分等)、贪心 - 图6 1.1 枚举(尺取法、前缀和、差分等)、贪心 - 图7
用差分+前缀和来做,时间复杂度:1.1 枚举(尺取法、前缀和、差分等)、贪心 - 图8

#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 1e5+10;
int diff[maxn];
int main(){
    int L,M,x,y,res=0;
    cin >> L >> M;
    while(M--){
        cin >> x >> y;
        diff[x]--;
        diff[y+1]++;
    } 
    res += diff[0]==0;
    for(int i=1;i<=L;i++){
        diff[i] += diff[i-1];
        res += diff[i]==0;
    }
    cout << res << endl;
    return 0;
}

1.1 枚举(尺取法、前缀和、差分等)、贪心 - 图9 1.1 枚举(尺取法、前缀和、差分等)、贪心 - 图10
离散化的写法,复杂度:1.1 枚举(尺取法、前缀和、差分等)、贪心 - 图11

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;

struct node{
    int x,y;
}arr[maxn];
bool cmp(node a,node b){
    if(a.x==b.x) return a.y<b.y;
    else return a.x<b.x;
}
int main(){
    int L,M,x,y,res=0;
    cin >> L >> M;
    for(int i=1;i<=M;i++){
        cin >> arr[i].x >> arr[i].y;
    }
    sort(arr+1,arr+M+1,cmp);
    res += arr[1].y-arr[1].x+1;
    int right=arr[1].y;
    for(int i=2;i<=M;i++){
        if(arr[i].x>right){
            res += arr[i].y-arr[i].x+1;
            right = arr[i].y;
        }
        else if(arr[i].y>=right){
            res += arr[i].y-right;
            right = arr[i].y;
        }
    }
    cout << L-res+1 << endl;
    return 0;
}