码迷,mamicode.com
首页 > 其他好文 > 详细

cogs 516【求和】【解题报告】

时间:2017-12-19 01:45:38      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:eve   lan   scan   ret   前缀   get   pos   oid   ++   

516. 求和

【问题描述】

给出一个数列A1,A2….,An和K,P。
设Sij=Ai+Ai+1+…+Aj
Anaswer=min{Si,j mod P | si,j mod P≥K),其中i≤j,(si,j mod P | si,j mod P≥K}非空。

【输入格式】
第一行一个正整数n,K,P。
第二行n个整数,表示一个数列A1,A2,…,An

【输出格式】
在第一行输出Answer。

【输入样例】
7 2 17
12
13
15
11
16
26
11

【输出样例】

2

【数据范围】
在100%的数据中,1<n<100000,1<K,P,ai<10^8,i=1,2…n

 

treap的题目

求出前缀和,一边求一边取膜,每一次插入一个前缀和x,插入之前去查找一个值y,使(x-y)%p>=k,我们分两种情况来讨论,x>=y和x<y,当x>=y时x-y是一个正数,我们直接在平衡树

中查找x-k的前驱,x-y即为所求值,取min;对于x<y,因为a全是正数,所以x取膜前一定比y取膜前大,那么我们可以对x+p,再-y,得到的即为当y>x时这一段取膜后的值,同样查找x+p-k的前驱。如果x+p-k查到的y<=x怎么办?其实不用管,因为他肯定不会比x-k查完之后求得的值更优。

技术分享图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int inf=100005;
 4 struct treap{
 5     int rnd;
 6     int l,r;
 7     int v;
 8     int siz;
 9     int w;
10 }t[inf];
11 void update(int x){
12     t[x].siz=t[t[x].l].siz+t[t[x].r].siz+t[x].w;
13 }
14 void lrot(int &x){
15     int k=t[x].r;
16     t[x].r=t[k].l;
17     t[k].l=x;
18     update(x);
19     update(k);
20     x=k;
21 }
22 void rrot(int &x){
23     int k=t[x].l;
24     t[x].l=t[k].r;
25     t[k].r=x;
26     update(x);
27     update(k);
28     x=k;
29 }
30 int rt,sz;
31 int a[inf],n,k,p,mi=0x7fffffff;
32 int Rand(){
33     return ((rand()<<12)+rand())%20021031;
34 }
35 void insert(int &x,int v){
36     if(!x){
37         x=++sz;
38         t[x].rnd=Rand();
39         t[x].v=v;
40         t[x].siz=t[x].w=1;
41         return ;
42     }
43     t[x].siz++;
44     if(t[x].v==v){
45         t[x].w++;
46         return ;
47     }
48     if(v<t[x].v){
49         insert(t[x].l,v);
50         if(t[t[x].l].rnd<t[x].rnd)rrot(x);
51     }
52     else {
53         insert(t[x].r,v);
54         if(t[t[x].r].rnd<t[x].rnd)lrot(x);
55     }
56 }
57 int pre(int x,int v,int Max){
58     if(!x)return Max;
59     if(t[x].v>v)return pre(t[x].l,v,Max);
60     else return pre(t[x].r,v,max(Max,t[x].v));
61 }
62 int main()
63 {
64     scanf("%d%d%d",&n,&k,&p);
65     insert(rt,0);
66     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
67     for(int i=1;i<=n;i++){
68         a[i]+=a[i-1];
69         a[i]%=p;
70         int tem1=pre(rt,a[i]-k,-0x3fffffff);
71         int tem2=pre(rt,a[i]+p-k,-0x3fffffff);
72         mi=min(mi,min(a[i]-tem1,a[i]+p-tem2));
73         insert(rt,a[i]);
74     }
75     printf("%d\n",mi);
76     return 0;
77 }
View Code

 

cogs 516【求和】【解题报告】

标签:eve   lan   scan   ret   前缀   get   pos   oid   ++   

原文地址:http://www.cnblogs.com/Turkeyghb/p/8059997.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!