80分求条,马蜂还算良好

P3586 [POI2015] LOG

chillLee @ 2024-12-03 17:59:45

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
int n, m;
int op[maxn];
int oa[maxn], ob[maxn];
int a[maxn]; // 原序列
int num[maxn];
ll sum[maxn];
int zero_num;
int dis[maxn], dcnt, cnt; // discretization
map<int, int > mp;

inline long long read(){
    char readch=getchar(); ll readtmp=0;
    ll readflag=1;
    while(readch<'0' || '9'<readch){if(readch=='-')readflag=-1;readch=getchar();}
    while('0'<=readch && readch<='9'){readtmp=readtmp*10+readch-'0';readch=getchar();}
    return readtmp*readflag;
}

void pre(){
    cin >> n >> m;
    zero_num = n;// 最开始全是0

    for(int i=1; i<=m; i++){
        char ch ;
        scanf(" %c", &ch);
        oa[i] = read();
        ob[i] = read();

        dis[++dcnt] = ob[i];

        if(ch == 'U') op[i] = 1;
        else op[i] = 2;
    }
    sort(dis+1, dis+1+dcnt);

    for(int i=1; i<=dcnt; i++){
        if(dis[i-1] == dis[i]) continue;//此时也避免了0的加入
        else {++cnt; mp[dis[i]] = cnt; dis[cnt] = dis[i];}
    }

}

// 建立两个树状数组,一个用于存每个位置有多少个数
// 另一个用于记录前缀和
// 每次查询,先记录 >=s 的数字的个数,再找 < s 的所有数求和是否能够凑出剩下的所有要求
// O(nlog)

void insert(int x, int y){
    for(; x <= cnt; x += x & (-x)) num[x] += y;
}
// cnt 是离散化后数量

int find(int s){
    int res = 0;
    for(; s; s -= s & (-s)) res += num[s]; 
    return res;
}
///

void add(int x, int y){
    for(; x <= cnt ; x += x & (-x)) sum[x] += y;
}

ll query(int s){
    ll res = 0;
    for(; s; s -= s & (-s)) res += sum[s];
    return res;
}

int main(){
    freopen("1.in", "r", stdin);

    pre();

    for(int i=1; i<=m; i++){
        if(op[i] == 1){
            int origin = a[oa[i]];
            a[oa[i]] = ob[i];
            if(origin) insert(origin, -1);
            if(ob[i]) insert(mp[ob[i]], 1);
            if(origin) add(mp[origin], -origin);
            if(ob[i]) add(mp[ob[i]], ob[i]);
            if(origin == 0 && ob[i]) zero_num--;
            else if(origin && ob[i] == 0) zero_num++;
        }
        else {
            int number = n - find(mp[ob[i]] - 1) - zero_num;
            //printf("number: %d, mo[ob[i]]: %d \n", number, mp[ob[i]]);
            if(oa[i] <= number){
                printf("TAK\n");
                continue;
            }
            ll tmp =  max(oa[i] - number, 0); tmp *= ob[i];
            int id = lower_bound(dis+1, dis+1+cnt, ob[i]) - dis;

            ll b = query(id-1);
            //printf("id: %d; b: %d; tmp: %d\n", id, b, tmp);
            if(b >= tmp) printf("TAK\n");
            else printf("NIE\n");
        }
    }

    return 0;
}

|