codoeforces 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 1142 10000000000000000 -10000000000000000143 */
View Code
赞 (0)