1.区间加法,单点查询
Code:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
int n, m ;
const int AX = 1e5+6;
int add[AX];
int a[AX];
int b[AX];
int len;
void update( int l , int r , int c ){
int lim = min( r , b[l] * len );
for( int i = l ; i <= lim ; i++ ){
a[i] += c;
}
if( b[l] != b[r] ){
for( int i = ( b[r] - 1 ) * len + 1 ; i <= r ; i++ ){
a[i] += c;
}
}
for( int i = b[l] + 1 ; i < b[r] ; i++ ) add[i] += c;
return;
}
int main(){
int n;
scanf("%d",&n);
int m = n;
len = sqrt(n);
for( int i = 1 ; i <= n ; i++ ){
scanf("%d",&a[i]);
}
for( int i = 1 ; i <= n ; i++ ){
b[i] = (( i - 1 ) / len) + 1 ;
}
int op,l,r,c;
while( m-- ){
scanf("%d%d%d%d",&op,&l,&r,&c);
if( !op ){
update( l , r , c );
}else{
int res = a[r] + add[b[r]] ;
printf("%d\n",res);
}
}
return 0 ;
}
2.给出一个长为n的数列,以及n个操作,操作0区间加法,操作1询问区间内小于某个值x的前驱(比其小的最大元素)。
Code:
#include <bits/stdc++.h>
using namespace std;
const int AX = 1e6+66;
set<int>s[AX];
int a[AX];
int b[AX];
int add[AX];
int len ;
void rebuild( int t ){
s[t].clear();
for( int i = ( t - 1 ) * len + 1 ; i <= t * len ; i++ ){
s[t].insert( a[i] );
}
return;
}
void update( int l , int r , int c ){
int lim = min( r , b[l] * len );
for( int i = l ; i <= lim ; i++ ){
a[i] += c;
}
rebuild( b[l] );
if( b[l] != b[r] ){
for( int i = ( b[r] - 1 ) * len + 1 ; i <= r ; i++ ){
a[i] += c;
}
rebuild( b[r] );
}
for( int i = b[l] + 1 ; i < b[r] ; i++ ) add[i] += c;
return;
}
int query( int l , int r , int c ){
int res = -1;
int lim = min( r , b[l] * len );
for( int i = l ; i <= lim ; i++ ){
int tmp = a[i] + add[b[i]];
if( tmp < c ){
res = max( res , tmp );
}
}
if( b[l] != b[r] ){
for( int i = ( b[r] - 1 ) * len + 1 ; i <= r ; i++ ){
int tmp = a[i] + add[b[i]];
if( tmp < c ){
res = max( res, tmp );
}
}
}
for( int i = b[l] + 1 ; i < b[r] ; i++ ){
int tmp = c - add[i];
set<int>::iterator it = s[i].lower_bound(tmp);
if( it == s[i].begin() ) continue;
it --;
res = max( (*it) + add[i] , res );
}
return res ;
}
int main(){
int n;
scanf("%d",&n);
int m = n;
len = 1000; //每块的长度。sqrt(n) 左右
for( int i = 1 ; i <= n ; i++ ){
scanf("%d",&a[i]);
}
for( int i = 1 ; i <= n ; i++ ){
b[i] = (( i - 1 ) / len) + 1 ;
s[b[i]].insert( a[i] );
}
int op,l,r,c;
while( m-- ){
scanf("%d%d%d%d",&op,&l,&r,&c);
if( !op ){
update( l , r , c );
}else{
int res = query(l,r,c) ;
printf("%d\n/",res);
}
}
return 0 ;
}