1. 程式人生 > >樹狀數組【洛谷P3586】 [POI2015]LOG

樹狀數組【洛谷P3586】 [POI2015]LOG

sig str sin 但是 scanf add char scan ons

P3586 [POI2015]LOG

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

離散化按照權值建立樹狀數組。

那麽對於大於s的值,可以直接減去s,這一部分的貢獻為\(c*(query_{geshu}(tot)-query_{geshu}(s-1))\)

剩下的數,我們只知道他們小於s,但是不知道確切的值所以並不能用上述方法求出貢獻。

但是我們知道每個數的大小,那麽可以求出每個數的權值*個數之和,這些是可以作為貢獻的。

也就是\(query_{quanzhi}(s-1)\)

註意離散化。

對於離散化,一定註意當前的值要用離散化之後的還是之前的。

之後的用\(lowerbound\)求出,之後的再用求出的序號帶入到離散化數組就可以。

code:

#include <iostream>
#include <cstdio>
#include <algorithm>


#define int long long

using namespace std;

const int wx=3000017;

inline int read(){
    int sum=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    return sum*f;
}

int a[wx],sum_geshu[wx],sum_quanzhi[wx],b[wx];
int n,m,tot;
int c[wx];
char opt[7];

struct node{
    int flag,num,to;
    int c,s;
}t[wx];

void add1(int pos,int k){
    for(int i=pos;i<=tot;i+=(i&-i))
        sum_geshu[i]+=k;
}

int query1(int pos){
    int re=0;
    for(int i=pos;i>=1;i-=(i&-i))
        re+=sum_geshu[i];
    return re;
}

void add2(int pos,int k){
    for(int i=pos;i<=tot;i+=(i&-i))
        sum_quanzhi[i]+=k;
}

int query2(int pos){
    int re=0;
    for(int i=pos;i>=1;i-=(i&-i))
        re+=sum_quanzhi[i];
    return re;
}



signed main(){
    n=read(); m=read();
    for(int i=1;i<=m;i++){
        scanf("%s",opt+1);
        if(opt[1]=='U'){
            t[i].flag=1;
            t[i].num=read();
            t[i].to=read();
            b[++tot]=t[i].to;
        }
        else{
            t[i].c=read();
            t[i].s=read();
            b[++tot]=t[i].s;
        }
    }
    sort(b+1,b+1+tot); 
    for(int i=1;i<=m;i++){
        if(t[i].flag){
            int tmp=lower_bound(b+1,b+1+tot,t[i].to)-b;
            if(a[t[i].num]){
                add1(a[t[i].num],-1);add2(a[t[i].num],-b[a[t[i].num]]);
            } 
            
            if(tmp){
                add1(tmp,1); a[t[i].num]=tmp; add2(tmp,b[tmp]);
            }
        }
        else{
            int s=lower_bound(b+1,b+1+tot,t[i].s)-b;
            int tmp=b[s]*(t[i].c-(query1(tot)-query1(s-1)));
            if(tmp<=query2(s-1))puts("TAK");
            else puts("NIE");
        }
    }
    return 0;
}

樹狀數組【洛谷P3586】 [POI2015]LOG