洛谷 P3586 [POI2015]LOG

-----

题链

题意:判断序列能否选择c个数字同时-1并执行s次,操作单点修改;

对于序列中>=s的数字,相当于那些数字就等于s,毕竟执行s次也不会把这些数字删成0;

结论就是八那些超过s的数字看作s,如果序列的总和>=c*s的话,就是可行的,否则不可行;

把每个数想象成不同颜色的楼房,比如 7 9 3 2 表示四栋楼房高度,询问能否每次选择3个数字-1并执行5次,就是选择3栋楼房砍去最上层;

7 9 3 2 转化为 5 5 3 2,因为每次都得选择3个不同颜色的楼房,不妨把颜色 3,4 的楼房叠在一起,那么序列就变成 5 5 5,每次砍去最上层且最上层颜色都不同;

也就是说把后一栋楼房的高度叠到前一栋楼房上,最高高度是s,这样能保证每次选择都是c个不同颜色楼房;

所以序列总和>=c*s则可行;

--动态开点权值线段树

吸氧才过的最后一个点...

//#include <bits/stdc++.h>
#include <iostream>
#include <algorithm> 
#include <ctime>
#include <cmath>
#include <stdio.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define LL long long
#define PI acos(-1.0)
#define eps 1e-8
#define Pair pair<double,double>
// notice
#define mod 998244353 
#define MAXN 1e9
#define MS 1000009

LL n,m;
LL a[MS];
struct node{
	int l,r;
	LL cnt,val;
}p[MS<<5];
int tot;
int root;

void push_up(int &rt){
	if(!p[rt].l && !p[rt].r){
		rt = 0;
	}
	else if(!p[rt].l){
		p[rt].cnt = p[p[rt].r].cnt;
		p[rt].val = p[p[rt].r].val;
	}
	else if(!p[rt].r){
		p[rt].cnt = p[p[rt].l].cnt;
		p[rt].val = p[p[rt].l].val;
	}
	else{
		p[rt].cnt = p[p[rt].l].cnt + p[p[rt].r].cnt;
		p[rt].val = p[p[rt].l].val + p[p[rt].r].val;
	}
}

void update(int &rt,int pos,int l,int r,LL val,int t){
	if(!rt) rt = ++tot;
	if(l == r){
		if(t){
			p[rt].cnt++;
			p[rt].val += val;
		}
		else{
			p[rt].cnt--;
			p[rt].val -= val;
		}
		if(p[rt].cnt == 0){
			rt = 0;
		}
		return;
	}
	int m = l+r>>1;
	if(m >= pos) update(p[rt].l,pos,l,m,val,t);
	else update(p[rt].r,pos,m+1,r,val,t);
	push_up(rt);
}

node get_cnt(int rt,int L,int R,int l,int r){
	if(!rt) return {0,0,0,0};
	if(L <= l && r <= R){
		return p[rt];
	}
	int m = l+r>>1;
	if(m < L) return get_cnt(p[rt].r,L,R,m+1,r);
	else if(m >= R) return get_cnt(p[rt].l,L,R,l,m);
	else{
		node ans;
		node t1 = get_cnt(p[rt].l,L,R,l,m);
		node t2 = get_cnt(p[rt].r,L,R,m+1,r);
		ans.cnt = t1.cnt + t2.cnt;
		ans.val = t1.val + t2.val;
		ans.l = p[rt].l;
		ans.r = p[rt].r;
		return ans;
	}
	
//	LL ans = 0;
//	if(m >= L) ans += get_cnt(p[rt].l,L,R,l,m);
//	if(m <  R) ans += get_cnt(p[rt].r,L,R,m+1,r);
//	return ans;
}

int main() {
	ios::sync_with_stdio(false);
	cin >> n >> m;
	for(int i=1;i<=n;i++) a[i] = -1;
	while(m--){
		char op;
		LL pos,val,c,s;
		cin >> op;
		if(op == 'U'){
			cin >> pos >> val;
			if(a[pos] != -1)
				update(root,a[pos],0,MAXN,a[pos],0);
			a[pos] = val;
			update(root,a[pos],0,MAXN,a[pos],1);
		}
		else if(op == 'Z'){
			cin >> c >> s;
			LL sum = p[root].val;
			node tt = get_cnt(root,s,MAXN,0,MAXN);
			sum -= tt.val;
			sum += tt.cnt*s;
			if(sum >= c*s){
				cout << "TAK\n";
			}
			else{
				cout << "NIE\n";
			}
		}
	}
	

	return 0;
}

--树状数组

把操作离线,数据离散化处理

//#include <bits/stdc++.h>
#include <iostream>
#include <algorithm> 
#include <ctime>
#include <cmath>
#include <stdio.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define LL long long
#define PI acos(-1.0)
#define eps 1e-8
#define Pair pair<double,double>
// notice
#define mod 998244353 
#define MAXN 1e9
#define MS 1000009

LL n,m;
LL a[MS],ta;
LL v[MS];
struct node{
	char op;
	LL x,y;
}b[MS];
struct nod{
	LL cnt,val;
}p[MS];

LL lowbit(LL x){
	return x&(-x);
}

void add(LL pos,LL val,LL t){
	for(;pos<=m;pos+=lowbit(pos)){
		if(t){
			p[pos].cnt++;
			p[pos].val += val;
		}
		else{
			p[pos].cnt--;
			p[pos].val -= val;
		}
	}
}

nod query(LL pos){
	nod ans = {0,0};
	for(;pos;pos-=lowbit(pos)){
		ans.cnt += p[pos].cnt;
		ans.val += p[pos].val;
	}
	return ans;
}

int main() {
	ios::sync_with_stdio(false);
	cin >> n >> m;
	for(int i=1;i<=m;i++){
		char op;
		LL x,y;
		cin >> op >> x >> y;
		b[i] = {op,x,y};
		a[i] = y;
	}
	sort(a+1,a+m+1);
	ta = 1;
	for(int i=2;i<=m;i++){
		if(a[i] != a[i-1]) a[++ta] = a[i];
	}
	for(int i=1;i<=m;i++) v[i] = -1;
	for(int i=1;i<=m;i++){
		node t = b[i];
		if(t.op == 'U'){
			LL pos;
			if(v[b[i].x] != -1){
				pos = lower_bound(a+1,a+ta+1,v[b[i].x]) - a;
				add(pos,v[b[i].x],0);
			}
			v[b[i].x] = b[i].y;
			pos = lower_bound(a+1,a+ta+1,v[b[i].x]) - a;
			add(pos,v[b[i].x],1);
		}
		else{
			nod sum = query(m);
			LL pos = lower_bound(a+1,a+ta+1,b[i].y) - a;
			nod tt = query(pos-1);
			LL cc = tt.val + (sum.cnt-tt.cnt)*b[i].y;
			if(cc >= b[i].x*b[i].y){
				cout << "TAK\n";
			}
			else{
				cout << "NIE\n";
			}
		}
	}
	
	

	return 0;
}

posted @ 2021-06-02 18:28  棉被sunlie  阅读(69)  评论(0)    收藏  举报