BZOJ2274: [Usaco2011 Feb]Generic Cow Protests

n<=100000个数,求划分为若干和不小于0的区间的方案数%1000000009。

注意模数啊啊啊。。f(i)--前i个数方案数,

n2过不了。不过上面那个东西就是找满足sum(i)>=sum(j)的f,随便线段树合并或者平衡树想必都可以写啦

然而splay写炸了。。求和最后一步旋转转错了。。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<algorithm>
  5 //#include<iostream>
  6 using namespace std;
  7 
  8 int n;
  9 #define maxn 100011
 10 int a[maxn],sum[maxn];
 11 const int mod=1000000009;
 12 struct Splay
 13 {
 14     struct Node
 15     {
 16         int id,v;
 17         int sum;
 18         int son[2],fa;
 19     }a[maxn];
 20     int size,root;
 21     Splay() {size=root=0;}
 22     void up(int x)
 23     {
 24         if (!x) return;
 25         const int &p=a[x].son[0],&q=a[x].son[1];
 26         a[x].sum=((a[p].sum+a[q].sum)%mod+a[x].v)%mod;
 27     }
 28     void rotate(int x)
 29     {
 30         const int y=a[x].fa,z=a[y].fa;
 31         bool w=(x==a[y].son[0]);
 32         a[x].fa=z;
 33         if (z) a[z].son[y==a[z].son[1]]=x;
 34         a[y].son[w^1]=a[x].son[w];
 35         if (a[x].son[w]) a[a[x].son[w]].fa=y;
 36         a[y].fa=x;
 37         a[x].son[w]=y;
 38         up(y);up(z);
 39     }
 40     void splay(int x)
 41     {
 42         while (a[x].fa)
 43         {
 44             const int y=a[x].fa,z=a[y].fa;
 45             if (z)
 46             {
 47                 if ((x==a[y].son[0])^(y==a[z].son[0])) rotate(x);
 48                 else rotate(y);
 49             }
 50             rotate(x);
 51         }
 52         up(x);root=x;
 53     }
 54     void insert(int v,int id)
 55     {
 56         if (!root)
 57         {
 58             root=++size;
 59             Node &now=a[size];
 60             now.v=v;now.id=id;now.sum=v;
 61             now.son[0]=now.son[1]=now.fa=0;
 62         }
 63         else
 64         {
 65             int x=root,last=0,from;
 66             while (x)
 67             {
 68                 last=x;
 69                 if (a[x].id<=id) x=a[x].son[from=1];
 70                 else x=a[x].son[from=0];
 71             }
 72             size++;Node &now=a[size];
 73             now.v=v;now.id=id;now.sum=v;
 74             now.son[0]=now.son[1]=0;now.fa=last;
 75             a[last].son[from]=size;
 76             up(last);
 77             splay(size);
 78         }
 79     }
 80     int find(int id)
 81     {
 82         int x=root,ans=0;
 83         while (x)
 84         {
 85             if (a[x].id<=id) ans=x,x=a[x].son[1];
 86             else x=a[x].son[0];
 87         }
 88         if (ans) splay(ans);
 89         return ans;
 90     }
 91     int sum(int id)
 92     {
 93         int x=find(id);
 94         if (!x) return 0;
 95         if (a[x].son[1])
 96         {
 97             int y=a[x].son[1];
 98             while (a[y].son[0]) y=a[y].son[0];
 99             splay(y);
100             return a[a[y].son[0]].sum;
101         }
102         else return a[x].sum;
103     }
104 }t;
105 int f[maxn];
106 int main()
107 {
108     scanf("%d",&n);
109     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
110     sum[0]=0;for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
111     f[0]=1;t.insert(f[0],0);
112     for (int i=1;i<=n;i++)
113     {
114         f[i]=t.sum(sum[i]);
115         t.insert(f[i],sum[i]);
116     }
117     printf("%d\n",f[n]);
118     return 0;
119 }
View Code

 

转载于:https://www.cnblogs.com/Blue233333/p/7513125.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值