codeforces 102920 I 题解

题意:

给你一个长为$n$的数字串,有正数和负数,和$m$个询问。每个询问询问你区间$[L,R]$中权值和小于$U$的子区间中权值和最大是多少。

$n<=2000,m<=200000$

可以发现,n很小,m较大,因此,我们可以先预处理出来所有子区间的和,然后将子区间按照权值和从小到大排序。然后我们对整个串进行分块。

对于每一个块,我们利用树状数组维护以这个块中的某个点为左端点的区间的最大值。对于块中的每个位置,我们利用树状数组维护以他为左端点的区间的最大值。

之后我们将询问也从小到大排列,将所有树状数组的初始值都赋为-inf。之后我们每计算一个询问,就把新的合法的序列放进对应的块的树状数组里以及他左端点的树状数组里。

询问的时候,对于整个块位于区间内的,查询块的树状数组的前缀最大值,否则便利位置,查每个位置树状数组的前缀最大值。

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<queue>
  7 #define N 2005
  8 #define M 200005
  9 #include<cmath>
 10 #define lowbit(i) (i&(-i))
 11 using namespace std;
 12 int n,m;
 13 int A[N];
 14 typedef pair<long long,pair<int,int>> T;
 15 long long ans[M];
 16 struct no{
 17     int l,r,bh;
 18     long long data;
 19 }q[M];
 20 priority_queue<T,vector<T>,greater<T > > q1;
 21 int len,bel[N];
 22 int st[N];
 23 long long B[N][N];
 24 long long C[N][N];
 25 bool cmp(const no &a,const no &b)
 26 {
 27     return a.data<b.data;    
 28 }
 29 void add1(int x,int y,long long data)
 30 {
 31     for(int i=y;i<=n;i+=lowbit(i))
 32     {
 33         B[x][i]=max(B[x][i],data);
 34     }
 35 }
 36 void add2(int x,int y,long long data)
 37 {
 38     for(int i=y;i<=n;i+=lowbit(i))
 39     {
 40         C[x][i]=max(C[x][i],data);
 41     }
 42 }
 43 long long get1(int x,int y)
 44 {
 45     long long ans=-1e17;
 46     for(int i=y;i;i-=lowbit(i))
 47     {
 48         ans=max(ans,B[x][i]);
 49     }
 50     return ans;
 51 }
 52 long long get2(int x,int y)
 53 {
 54     long long ans=-1e17;
 55     for(int i=y;i;i-=lowbit(i))
 56     {
 57         ans=max(ans,C[x][i]);
 58     }
 59     return ans;
 60 }
 61 long long que(int l,int r)
 62 {
 63     if(bel[l]==bel[r])
 64     {
 65         long long ans=-1e17;
 66         for(int i=l;i<=r;i++)
 67         {
 68             ans=max(ans,get1(i,r));
 69         }
 70         return ans;
 71     }
 72     long long ans=-1e17;
 73     for(int i=l;i<st[bel[l]+1];i++)
 74     {
 75         ans=max(ans,get1(i,r));
 76     }
 77     for(int i=bel[l]+1;i<bel[r];i++) ans=max(ans,get2(i,r));
 78     for(int i=st[bel[r]];i<=r;i++)
 79     {
 80         ans=max(ans,get1(i,r));
 81     }
 82     return ans;
 83 }
 84 int main()
 85 {
 86     scanf("%d%d",&n,&m);
 87     for(int i=1;i<=n;i++)
 88     {
 89         scanf("%d",&A[i]);
 90     }
 91     len=sqrt(n);
 92     for(int i=1;i<=n;i++)
 93     {
 94         bel[i]=(i-1)/len+1;
 95         if(!st[bel[i]])st[bel[i]]=i;
 96     }
 97     for(int i=1;i<=n;i++)
 98     {
 99         for(int j=0;j<=n;j++) B[i][j]=C[i][j]=-1e17;
100     }
101     bel[n+1]=bel[n]+1;
102     st[bel[n+1]]=n+1;
103     for(int i=1;i<=n;i++)
104     {
105         long long ans=0;
106         for(int j=i;j<=n;j++)
107         {
108             ans+=A[j];
109             T x;
110             x.first=ans;
111             x.second.first=i;
112             x.second.second=j;
113             q1.push(x);
114         }
115     }
116     for(int i=1;i<=m;i++)
117     {
118         scanf("%d%d%lld",&q[i].l,&q[i].r,&q[i].data);
119         q[i].bh=i;
120     }
121     sort(q+1,q+m+1,cmp);
122     for(int i=1;i<=m;i++)
123     {
124         while(!q1.empty()&&q1.top().first<=q[i].data)
125         {
126             T x=q1.top();q1.pop();
127             add1(x.second.first,x.second.second,x.first);
128             add2(bel[x.second.first],x.second.second,x.first);
129         }
130         ans[q[i].bh]=que(q[i].l,q[i].r);
131     }
132     for(int i=1;i<=m;i++)
133     {
134         if(ans[i]==-1e17)
135             printf("NONE\n");
136         else printf("%lld\n",ans[i]);
137     }
138     return 0;
139 }
140 /*
141 2 1
142 10000000000000000 -10000000000000000
143 */ 
View Code

 

posted @ 2021-02-19 09:52  Hzoi_joker  阅读(145)  评论(0编辑  收藏  举报