uva 12003 分块

 大白上的原题,我就练练手。。。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 10;
const int SIZE = 4096;
ll block[N / SIZE + 1][SIZE + 1];
ll A[N];

int query(int L, int R, int v)
{
    int k = 0;
    int lb = L / SIZE, rb = R / SIZE;
    if(lb == rb) { for(int i = L; i <= R; ++i) if(A[i] < v) k++; }
    else {
            for(int i = L; i < (lb + 1) * SIZE; ++i) if(A[i] < v) k++;
            for(int i = rb * SIZE; i <= R; ++i) if(A[i] < v) k++;
            for(int i = lb + 1; i < rb; ++i) {
                k += lower_bound(block[i], block[i] + SIZE, v) - block[i];
            }
    }
    return k;
}
void change(int k, int u, int p, int L, int R)
{
    ll x = (ll)u * k / (R - L + 1);
    if(A[p] == x) return;

    int la = p / SIZE;
    ll* B = &block[la][0];
    int pos = 0;
    ll old = A[p];
    while(B[pos] < old) pos++;
    A[p] = x; B[pos] = x;
    if(x > old) {
        while(pos < SIZE - 1 && B[pos] > B[pos + 1]) { swap(B[pos + 1], B[pos]); pos++; }
    }
    else {
        while(pos > 0 && B[pos] < B[pos - 1]) { swap(B[pos - 1], B[pos]); pos--; }
    }
}
int main()
{
    int n, m, u;
    while(~scanf("%d%d%d", &n, &m, &u))
    {
        int j = 0, k = 0;
        for(int i = 0; i < n; ++i)
        {
            scanf("%lld", &A[i]);
            block[k][j++] = A[i];
            if(j == SIZE) { k++; j = 0; }
        }
        for(int i = 0; i < k; ++i) sort(block[i], block[i] + SIZE);
        if(j) sort(block[k], block[k] + j);
        int L, R, v, p;
        while(m --)
        {
            int ans = 0;
            scanf("%d%d%d%d", &L, &R, &v, &p);
            L--; R--; p--;
            ans = query(L, R, v);
            change(ans, u, p, L, R);
        }
        for(int i = 0; i < n; ++i) printf("%lld\n", A[i]);
    }
    return 0;
}
  

 

转载于:https://www.cnblogs.com/orchidzjl/p/4905541.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值