1. 程式人生 > >BZOJ_4378_[POI2015]Logistyka_樹狀數組

BZOJ_4378_[POI2015]Logistyka_樹狀數組

long long sum scrip #define 進行 con 支持 har wid

BZOJ_4378_[POI2015]Logistyka_樹狀數組

Description

維護一個長度為n的序列,一開始都是0,支持以下兩種操作:
1.U k a 將序列中第k個數修改為a。
2.Z c s 在這個序列上,每次選出c個正數,並將它們都減去1,詢問能否進行s次操作。
每次詢問獨立,即每次詢問不會對序列進行修改。

Input

第一行包含兩個正整數n,m(1<=n,m<=1000000),分別表示序列長度和操作次數。
接下來m行為m個操作,其中1<=k,c<=n,0<=a<=10^9,1<=s<=10^9。

Output

包含若幹行,對於每個Z詢問,若可行,輸出TAK,否則輸出NIE。

Sample Input

3 8
U 1 5
U 2 7
Z 2 6
U 3 1
Z 2 6
U 2 2
Z 2 6
Z 2 1

Sample Output

NIE
TAK
NIE
TAK

需要註意查詢是在整個序列上的而不是給定區間。 假設大於s的個數有k個,則剩下的那些權值和必須要大於等於(c-k)*s。 於是我們把權值離散化然後用兩個樹狀數組分別維護。 代碼:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000050
#define RR register
typedef long long ll;
int n,m,t[N],maxn=1000000000,h[N],p[N];
ll c[N][2];
char opt[10];
inline int rd() {
    RR int x=0,f=1; RR char s=getchar();
    while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();}
    while(s>=‘0‘&&s<=‘9‘){x=(x<<3)+(x<<1)+s-‘0‘;s=getchar();}
    return x*f;
}
struct A {
    int num,v,id,opt,pos;
}a[N];
inline bool cmp1(const A &x,const A &y){return x.num<y.num;}
inline bool cmp2(const A &x,const A &y){return x.id<y.id;}
void fix(int x,int v,int flg) {
    for(;x<=m;x+=x&(-x)) c[x][flg]+=v;
}
ll inq(int x,int flg) {
    ll re=0;
    for(;x;x-=x&(-x)) re+=c[x][flg];
    return re;
}
int main() {
    n=rd(); m=rd();
    int i,j;
    for(i=1;i<=m;i++) {
        scanf("%s",opt);
        if(opt[0]==‘U‘) {
            a[i].opt=1; a[i].id=i; a[i].pos=rd(); a[i].num=rd();
        }else {
            a[i].opt=2; a[i].id=i; a[i].pos=rd(); a[i].num=rd();
        }
    }
    sort(a+1,a+m+1,cmp1); a[0].num=134234;
    for(j=0,i=1;i<=m;i++) {
        if(a[i].num!=a[i-1].num) j++;
        a[i].v=j;
        h[j]=a[i].num;
    }
    sort(a+1,a+m+1,cmp2);
    for(i=1;i<=m;i++) {
        if(a[i].opt==1) {
            int t=a[i].pos;
            if(p[t]) {
                fix(p[t],-1,1);
                fix(p[t],-h[p[t]],2);
            }
            p[t]=a[i].v;
            fix(p[t],1,1);
            fix(p[t],h[p[t]],2);
        }else {
            int k=inq(m,1)-inq(a[i].v-1,1);
            if(k>=a[i].pos) {
                puts("TAK"); continue;
            }
            ll sum=inq(a[i].v-1,2);
            puts(sum>=1ll*a[i].num*(a[i].pos-k)?"TAK":"NIE");
        }
    }
}

技術分享圖片

BZOJ_4378_[POI2015]Logistyka_樹狀數組