UVA 1400 线段树

input

n m  1<=n,m<=500000

a1 a2 ... an   |ai|<=1e9

m行查询

每行一对a b

output

对于每对a b输出区间[a,b]中最小连续和x y,如果有多组满足,输出x最小,如果还有多组满足,输出y最小

  1 #include <cstdio>
  2 #include <queue>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <cstdlib>
  6 #include <algorithm>
  7 #include <vector>
  8 #include <map>
  9 #include <set>
 10 #include <ctime>
 11 #include <cmath>
 12 #define MAX 500000
 13 
 14 using namespace std;
 15 
 16 struct pos
 17 {
 18     int s,e;
 19     bool operator<(const pos&a)const
 20     {
 21         if(s!=a.s) return s<a.s;
 22         return e<a.e;
 23     }
 24 };
 25 struct node
 26 {
 27     long long sum,suf,pre;
 28     int pree,sufs;
 29 };
 30 long long sum[MAX*3],pre[MAX*3],sub[MAX*3],suf[MAX*3],maxsum;
 31 int n,m,pree[MAX*3],sufs[MAX*3],a,b,cas=1;
 32 pos subp[MAX*3],minp;
 33 void build(int l,int r,int k)
 34 {
 35     if(l==r)
 36     {
 37         scanf("%lld",&sum[k]);
 38         pre[k]=suf[k]=sum[k];
 39         pree[k]=sufs[k]=subp[k].s=subp[k].e=l;
 40         sub[k]=sum[k];
 41         return;
 42     }
 43     int m=l+((r-l)>>1),lc=k<<1,rc=(k<<1)+1;
 44     build(l,m,lc);
 45     build(m+1,r,rc);
 46     sum[k]=sum[lc]+sum[rc];            //sum
 47     pre[k]=sum[lc]+pre[rc];            //pre
 48     pree[k]=pree[rc];
 49     if(pre[k]<=pre[lc])
 50     {
 51         pre[k]=pre[lc];
 52         pree[k]=pree[lc];
 53     }
 54     suf[k]=suf[lc]+sum[rc];            //suf
 55     sufs[k]=sufs[lc];
 56     if(suf[k]<suf[rc])
 57     {
 58         sufs[k]=sufs[rc];
 59         suf[k]=suf[rc];
 60     }
 61     sub[k]=pre[rc]+suf[lc];            //sub
 62     subp[k].s=sufs[lc],subp[k].e=pree[rc];
 63     if(sub[k]<sub[rc])
 64     {
 65         sub[k]=sub[rc];
 66         subp[k]=subp[rc];
 67     }
 68     else if(sub[k]==sub[rc]) subp[k]=min(subp[k],subp[rc]);
 69     if(sub[k]<sub[lc])
 70     {
 71         sub[k]=sub[lc];
 72         subp[k]=subp[lc];
 73     }
 74     else if(sub[k]==sub[lc]) subp[k]=min(subp[k],subp[lc]);
 75 }
 76 node query(int l,int r,int k)
 77 {
 78     if(a<=l&&b>=r)
 79     {
 80         if(sub[k]>maxsum)
 81         {
 82             maxsum=sub[k];
 83             minp=subp[k];
 84         }
 85         else if(sub[k]==maxsum) minp=min(minp,subp[k]);
 86         node u;
 87         u.pre=pre[k];u.pree=pree[k];u.sum=sum[k];u.suf=suf[k];u.sufs=sufs[k];
 88         return u;
 89     }
 90     int m=l+((r-l)>>1),lc=k<<1,rc=(k<<1)+1;
 91     node lcc,rcc;
 92     if(a<=m) lcc=query(l,m,lc);
 93     if(b>m) rcc=query(m+1,r,rc);
 94     if(a<=m&&b>m)
 95     {
 96         node u;
 97         u.sum=lcc.sum+rcc.sum;            //sum
 98         u.pre=lcc.sum+rcc.pre;            //pre
 99         u.pree=rcc.pree;
100         if(u.pre<=lcc.pre)
101         {
102             u.pre=lcc.pre;
103             u.pree=lcc.pree;
104         }
105         u.suf=lcc.suf+rcc.sum;            //suf
106         u.sufs=lcc.sufs;
107         if(u.suf<rcc.suf)
108         {
109             u.sufs=rcc.sufs;
110             u.suf=rcc.suf;
111         }
112         long long subk=rcc.pre+lcc.suf;            //sub
113         pos subpk;
114         subpk.s=lcc.sufs,subpk.e=rcc.pree;
115         if(subk>maxsum)
116         {
117             maxsum=subk;
118             minp=subpk;
119         }
120         else if(subk==maxsum) minp=min(minp,subpk);
121         return u;
122     }
123     else if(a<=m) return lcc;
124     else return rcc;
125 }
126 int main()
127 {
128     freopen("/home/user/桌面/in","r",stdin);
129     while(scanf("%d%d",&n,&m)==2)
130     {
131         build(1,n,1);
132         printf("Case %d:
",cas++);
133         while(m--)
134         {
135             scanf("%d%d",&a,&b);
136             minp.s=minp.e=n;
137             maxsum=-0x7fffffff-1;
138             query(1,n,1);
139             printf("%d %d
",minp.s,minp.e);
140         }
141     }
142     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
143     return 0;
144 }
View Code
原文地址:https://www.cnblogs.com/cdyboke/p/4987410.html