P2344 奶牛抗议(二维偏序+$dp$(!树状数组$0$基准!))
二维偏序$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('\n'); 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 ̄)づ╭❤~