TOJ 3425: Generic Cow Protests -- 树状数组

本文介绍了一道名为GenericCowProtests的算法题,任务是将N头奶牛按正整数组划分,使得每组的和为正数,并计算划分方式的数量。使用树状数组等数据结构进行高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

3425: Generic Cow Protests

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 46            Accepted:14

Description

Farmer John's N (1 <= N <= 100,000) cows are lined up in a row and numbered 1..N. The cows are conducting another one of their strange protests, so each cow i is holding up a sign with an integer A_i
(-10,000 <= A_i <= 10,000).

FJ knows the mob of cows will behave if they are properly grouped and thus would like to arrange the cows into one or more contiguous groups so that every cow is in exactly one group and that every
group has a nonnegative sum.

Help him count the number of ways he can do this, modulo 1,000,000,009.

By way of example, if N = 4 and the cows' signs are 2, 3, -3, and 1, then the following are the only four valid ways of arranging the cows:

(2 3 -3 1)
(2 3 -3) (1)
(2) (3 -3 1)
(2) (3 -3) (1)

Note that this example demonstrates the rule for counting different orders of the arrangements.

Input

* Line 1: A single integer: N

* Lines 2..N + 1: Line i + 1 contains a single integer: A_i

Output

* Line 1: A single integer, the number of arrangements modulo 1,000,000,009.

Sample Input

4
2
3
-3
1

Sample Output

4

Source

USACO Feb 2011


http://www.verydemo.com/demo_c427_i28080.html 有详细的解答

#include 
    
     
#include 
     
      
#include 
      
       
#include 
       
        
#include 
        
         
#include 
          #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include 
               
                 #include 
                
                  #include 
                 
                   #include 
                  
                    #include 
                   
                     #define mp make_pair using namespace std; typedef unsigned int ui; typedef long long ll; typedef unsigned long long ull; typedef pair
                    
                      pii; typedef vector
                     
                       vi; typedef vi::iterator vi_it; typedef map
                      
                        mii; typedef priority_queue
                       
                         pqi; typedef priority_queue
                        
                         , greater
                         
                           > rpqi; const int MAX_N = 100000 + 2; const int MOD = 1000000009; int sum[MAX_N]; int ordered_sum[MAX_N]; int c[MAX_N]; class Tree_Array { public: Tree_Array(int _n); void update(int pos, int v); int sum(int pos); private: int n; inline int lowbit(int x); }; Tree_Array::Tree_Array(int _n) : n(_n) { } inline int Tree_Array::lowbit(int x) { return x & (-x); } void Tree_Array::update(int pos, int v) { for (int i = pos; i <= n; i += lowbit(i)) { c[i] = (c[i] + v) % MOD; } } int Tree_Array::sum(int pos) { int ret = 0; for (int i = pos; i; i -= lowbit(i)) { ret = (ret + c[i]) % MOD; } return ret; } int main(int argc, char *argv[]) { // freopen("D:\\in.txt", "r", stdin); int n, a, i; cin >> n; Tree_Array ta(n); for (i = 1; i <= n; ++i) { scanf("%d", &a); ordered_sum[i] = sum[i] = sum[i - 1] + a; } sort(ordered_sum + 1, ordered_sum + n + 1); int *end = unique(ordered_sum + 1, ordered_sum + n + 1); for (i = 1; i < n; ++i) { int pos = lower_bound(ordered_sum + 1, end, sum[i]) - ordered_sum; int tmp = ta.sum(pos); if (sum[i] >= 0) { ++tmp; } ta.update(pos, tmp); } cout << (ta.sum(lower_bound(ordered_sum + 1, end, sum[n]) - ordered_sum) + (sum[n] >= 0)) % MOD << endl; return 0; } 
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
        
       
      
     
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值