题意:
给定一个序列,要求查询一个区间内有多少个数小于v。并且把第p个位置的值改为u * k / (R - L + 1)。
思路:
单点修改和区间查询。
线段树的话还要套平衡树,不会写,也不想写(:зゝ∠)
还是分块搞吧。。
把n个数分成 sqrt(n)个区间,然后把每个区间内都排序。
对于查询的时候,对于完全覆盖的块直接二分查,对于没完全覆盖的两端,直接暴力扫。
修改的时候,对于原数据直接改,对于排序后的要注意存的时候存上id,这样找出p在哪一块,直接覆盖掉,但是覆盖掉可能比原来的值大或者小,那么就直接交换到合适的位置就好了。
代码:
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <math.h>
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define ff first
#define ss second
#define pb push_back
#define ll long long
#define mod 1000000007
#define ull unsigned long long
#define mst(ss,b) memset(ss,b,sizeof(ss));
#define pl(x) cout << #x << "= " << x << endl;
const int inf = 0x3f3f3f3f;
const int N = 3e5+5;
int n, m, u;
int num, blocks;
ll ans[N], a[N];
//num分块的个数
//blocks表示块的大小
struct node{
ll v;
int id;
node(int a = 0, int b = 0) {
v = a, id = b;
}
bool operator < (const node& rhs)const {
return v<rhs.v;
}
};
vector<node>q[1000];
int query(int L, int R, int v){
int posL = (L-1)/blocks;
int posR = (R-1)/blocks;
if(posL == posR){
int k = 0;
for(int i=L; i<=R; i++)if(a[i] < v)k++;
return k;
}
int k = 0;
for(int i=L; i<=(posL+1)*blocks; i++)if(a[i] < v)k++;
for(int i=posR*blocks+1; i<=R; i++)if(a[i] < v)k++;
for(int i=posL+1; i<posR; i++)k += lower_bound(q[i].begin(), q[i].end(), v) - q[i].begin();
return k;
}
void update(int p, ll v){
a[p] = v;
int cur = (p-1)/blocks;
for(int i=0; i<q[cur].size(); i++){
if(q[cur][i].id == p){
if(q[cur][i].v == v)return ;
q[cur][i].v = v;
int pos = i;
while(pos > 0 && q[cur][pos].v < q[cur][pos-1].v){
swap(q[cur][pos], q[cur][pos-1]);
pos--;
}
while(pos < q[cur].size()-1 && q[cur][pos].v > q[cur][pos+1].v){
swap(q[cur][pos], q[cur][pos+1]);
pos++;
}
return ;
}
}
}
int main(){
scanf("%d%d%d", &n, &m, &u);
blocks = sqrt(n);
for(int i=1; i<=n; i++){
scanf("%lld", &a[i]);
q[num].pb(node(a[i], i)); //
if(i/blocks != num)num++;
}
if(num * blocks != n)num++;
for(int i=0; i<num; i++)sort(q[i].begin(), q[i].end());
while(m--){
int L, R, v, p;
scanf("%d%d%d%d", &L, &R, &v, &p);
int k = query(L, R, v);
update(p, 1LL*u*k/(R-L+1));
}
for(int i=0; i<num; i++)
for(int j=0; j<q[i].size(); j++)ans[q[i][j].id] = q[i][j].v;
for(int i=1; i<=n; i++)printf("%lld\n", ans[i]);
return 0;
}