• P2344 奶牛抗议(二维偏序+$dp$(!树状数组$0$基准!))


    ${color{cyan}{>>Question}}$

    二维偏序$dp$

    方程很简单

    令$f[i]$表示到$i$的方案数

    有$$f[i] = sum f[j],sum_{k = j+1}^i a[k] geq 0$$

    写成前缀和的形式便是$$f[i] = sum f[j],sum[i]-sum[j]geq 0$$

    观察可知$i$由$j$转移来有两个条件

    $1.$ $j < i$

    $2.$ $sum[j] <= sum[i]$

    那可把$i$看成$(i,sum[i])$的点,就成了一个二维偏序问题

    可以离散化,也可以不离散化

    离散化就离散$sum[i]$,$i$天然有序

    不离散化就以$sum[i]$为第一关键字,$i$为第二关键字排序

    外面都套个树状数组即可

    但我太菜了,第一次处理树状数组$0$基准的情况($f[0] = 1$),犯了很多错才调出来,具体看代码吧

    离散化版

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <queue>
     6 #define ll long long
     7 using namespace std; 
     8 
     9 template <typename T> void in(T &x) {
    10     x = 0; T f = 1; char ch = getchar();
    11     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    12     while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
    13     x *= f;
    14 }
    15 
    16 template <typename T> void out(T x) {
    17     if(x < 0) x = -x , putchar('-');
    18     if(x > 9) out(x/10);
    19     putchar(x%10 + 48);
    20 }
    21 //-------------------------------------------------------
    22 
    23 const int N = 1e5+7,mod = 1e9+9;
    24 int n;
    25 ll b[N],ans;
    26 
    27 struct node {
    28     int pos;ll sum;
    29 }p[N];
    30 
    31 struct map {
    32     int pos;ll sum;
    33     bool operator < (const map &x) const {
    34         return sum == x.sum ? pos < x.pos : sum < x.sum;//sum < x.sum;
    35     }
    36 }a[N];
    37 
    38 void A(int pos,ll k) {
    39     for(int i = pos;i <= n;i += i&-i) b[i] = (b[i]+k)%mod;
    40 }
    41 
    42 ll Q(int pos) {
    43     ll res = 0;
    44     for(int i = pos;i;i -= i&-i) res = (res + b[i])%mod;
    45     return res;
    46 }
    47 
    48 int main() {
    49     //freopen("0.in","r",stdin);
    50     //freopen("my.out","w",stdout);
    51     int i; ll x;
    52     in(n);
    53     a[0].pos = a[0].sum = 0;
    54     for(i = 1;i <= n; ++i) p[i].pos = i,in(x),p[i].sum = p[i-1].sum + x,a[i].pos = i,a[i].sum = p[i].sum;
    55     sort(a,a+n+1);//debug a[0]
    56     p[a[0].pos].sum = 1; int _id = 1;
    57     for(i = 1;i <= n; ++i) {
    58         if(a[i].sum != a[i-1].sum) ++_id;//debug i-1越界 
    59         p[a[i].pos].sum = _id;
    60     }
    61     //for(i = 1;i <= n; ++i) cout << p[i].sum << endl;
    62     A(p[0].sum,1);
    63     for(i = 1;i <= n; ++i) {
    64         ans = Q(p[i].sum);
    65         A(p[i].sum,ans);
    66         if(i == n) out(ans);
    67         //out(ans),putchar('
    ');
    68     }
    69     //out(ans);
    70     return 0;
    71 }

    不离散化版

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <queue>
     6 #define ll long long
     7 using namespace std; 
     8 
     9 template <typename T> void in(T &x) {
    10     x = 0; T f = 1; char ch = getchar();
    11     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    12     while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
    13     x *= f;
    14 }
    15 
    16 template <typename T> void out(T x) {
    17     if(x < 0) x = -x , putchar('-');
    18     if(x > 9) out(x/10);
    19     putchar(x%10 + 48);
    20 }
    21 //-------------------------------------------------------
    22 
    23 const int N = 1e5+7,mod = 1e9+9;
    24 int n;
    25 ll b[N],ans;
    26 ll f[N];
    27 
    28 struct node {
    29     int pos;ll sum;
    30     bool operator < (const node &x) const {
    31         return sum == x.sum ? pos < x.pos : sum < x.sum;
    32     }
    33 }p[N];
    34 
    35 void A(int pos,ll k) {
    36     for(int i = pos;i <= n+1;i += i&-i) b[i] = (b[i]+k)%mod;//debug n+1 -> n
    37 }
    38 
    39 ll Q(int pos) {
    40     ll res = 0;
    41     for(int i = pos;i;i -= i&-i) res = (res + b[i])%mod;
    42     return res;
    43 }
    44 
    45 int main() {
    46     //freopen("0.in","r",stdin);
    47     int i; ll x;
    48     in(n);
    49     p[0].pos = 1,p[0].sum = 0;
    50     for(i = 1;i <= n; ++i) p[i].pos = i+1,in(x),p[i].sum = p[i-1].sum + x;
    51     sort(p,p+n+1);
    52     for(i = 0;i <= n; ++i) {
    53         if(p[i].pos == 1) A(p[i].pos,1);
    54         f[p[i].pos-1] = Q(p[i].pos);
    55         ll x = f[p[i].pos-1];
    56         //if(p[i].pos == 1) A(p[i].pos,1);//debug//debug 
    57         if(p[i].pos == 1) continue;
    58         A(p[i].pos,x);
    59     }
    60     out(f[n]);
    61     //for(i = 1;i <= n; ++i) cout << f[i] << endl;
    62     return 0;
    63 }

    谢谢各位看官老爷支持(づ ̄3 ̄)づ╭❤~

  • 相关阅读:
    一天一个Linux命令--find
    一天一个Linux命令--dhclient
    一道CTF题引发的思考——SSI注入
    netcat的简单使用(一)
    文件头类型
    windows10禁用更新方法
    Burpsuite 之intruder
    localstorage sessionstorage和cookie的区别
    js中的迭代方法-every, some, filter, map, forEach
    前端日志分类
  • 原文地址:https://www.cnblogs.com/mzg1805/p/11387673.html
Copyright © 2020-2023  润新知