序列

题目:

给定一个序列,求和最小且为正奇数的区间,如果有多个,则输出字典序最小

【输入格式】
第一行:一个正整数 n。
第二行:n 个整数,第 i 个代表 a i 。
【输出格式】
共一行。
若有解:三个整数,最小权值和,区间左端点,区间右端点。
若无解:一个字符串"-1"(不带引号)。
【样例输入 1】
5
1 -1 3 -2 3
【样例输出 1】
1 1 1

给定一个序列,求权值和为正奇数且最小的区间。
先处理出所有的前缀和,按顺序把它们丢到set 里。
因为要求权值和为正数且最小,那么只需lower_bound 找到在其前面
的第一个元素,用两者差更新答案。
对于奇偶性的要求,那用两个set 分开维护奇数和偶数就好了。
O(n log n)。

不会用STL,直接打的平衡树,没有删除操作,并不难打

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 using namespace std;
  7 struct Node
  8 {
  9   long long key,lev;
 10   int p;
 11   Node *ch[2];
 12 }treap[600001],*root[2];
 13 Node *pos=treap;
 14 long long sum[300001],S,ans=2e15;
 15 int n,L=2e9,R=2e9,P;
 16 queue<Node*>mem;
 17 void NewNode(Node* &r,long long key,int p)
 18 {
 19     if (mem.empty()) 
 20     r=pos++;
 21     else r=mem.front(),mem.pop();
 22     r->key=key;
 23     r->p=p;
 24     r->lev=rand();
 25     r->ch[0]=r->ch[1]=0;
 26 }
 27 void rotate(Node* &r,bool t)
 28 {
 29     Node* y=r->ch[!t];
 30     r->ch[!t]=y->ch[t];
 31     y->ch[t]=r;
 32     r=y;   
 33 }
 34 void insert(Node* &r,long long key,int p)
 35 {
 36   if (!r) NewNode(r,key,p);
 37   else 
 38     {
 39       bool t=r->key<key;
 40       insert(r->ch[t],key,p);
 41     if (r->ch[t]!=0&&r->ch[t]->lev<r->lev) rotate(r,!t);
 42     }
 43 }
 44 void find(Node* r,long long key)
 45 {
 46   if (!r) return;
 47   if (r->key<key)
 48     {
 49       if (r->key>S)
 50     {
 51       S=r->key;
 52       P=r->p;
 53     }
 54       else if (r->key==S)
 55     {
 56       P=min(P,r->p);
 57     }
 58     }
 59   if (r->key>key&&r->ch[0]) find(r->ch[0],key);
 60   else if (r->key<key&&r->ch[1]) find(r->ch[1],key);
 61 }
 62 int main()
 63 {int i;
 64   cin>>n;
 65   for (i=1;i<=n;i++)
 66     {
 67       scanf("%lld",&sum[i]);
 68       sum[i]+=sum[i-1];
 69     }
 70   insert(root[0],0,0);
 71   for (i=1;i<=n;i++)
 72     {
 73       S=-2e15;P=2e9;
 74       if (sum[i]%2==1)
 75     {
 76       find(root[0],sum[i]);
 77       if (S!=-2e15&&P!=2e9)
 78         {
 79           if (sum[i]-S<ans)
 80         {
 81           L=P;R=i;
 82           ans=sum[i]-S;
 83         }
 84           else if (sum[i]-S==ans)
 85         {
 86           if (P<L||(P==L&&i<R))
 87             {
 88               L=P;R=i;
 89             }
 90         }
 91         }
 92     }
 93       else
 94     {
 95       find(root[1],sum[i]);
 96       if (S!=-2e15&&P!=2e9)
 97         {
 98           if (sum[i]-S<ans)
 99         {
100           L=P;R=i;
101           ans=sum[i]-S;
102         }
103           else if (sum[i]-S==ans)
104         {
105           if (P<L||(P==L&&i<R))
106             {
107               L=P;R=i;
108             }
109         }
110         }
111     } 
112       insert(root[sum[i]%2],sum[i],i);
113     }
114   if (L==2e9&&R==2e9)
115     cout<<-1;
116   else cout<<ans<<' '<<L+1<<' '<<R;
117 }

 

posted @ 2017-10-02 17:15  Z-Y-Y-S  阅读(249)  评论(0编辑  收藏  举报