zoukankan      html  css  js  c++  java
  • luoguP2161 [SHOI2009]会场预约

    luoguP2161 [SHOI2009]会场预约

    好久没打线段树了...为不会做找借口

    https://www.luogu.org/problem/P2161

    题意:

    大概是说,一开始全空序列,之后开始安排招待会议,输入有q个操作,分两种:

    A l r : 将[l , r]占了,以前在 【l , r】的会议取消,并输出取消会议的个数

    B : 输入当前存在的会议

    首先我们需要理清问题的实质:这里我们将每个会议看成一个颜色
    操作A实质:查询一段区间内有多少种颜色,再清空这区间里的每种颜色所属的区域,再在这一区间填上另一种颜色

    其实就是一个删除操作难想,其实不用真正的删除,用一个del[]记录每种颜色是否被删,然后在更新A,B操作答案的时候判一下就行了
    因题而异吧

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int MAX = 200000+99;
    
    int q;
    struct tree{
    	int is, set;
    	//is:区间o是否为一种颜色 
    }tr[MAX<<2];
    int del[MAX], del_n, ans;
    //ans表示还剩颜色数,del_n表示每次删除颜色的数目,del保存该颜色是否已经被清除 
    
    void build(int o, int l, int r) {
    	tr[o].is = 1, tr[o].set = 0;
    	if(l == r) return ;
    	int mid = (l+r)>>1;
    	build(o<<1, l, mid);
    	build(o<<1|1, mid+1, r);
    }
    
    void pushdown(int o) {
    	tr[o].is = 0;//下放后该区间颜色不一 (要先写这个!!,因为可能它没有set,但是却为不同颜色 
    	if(tr[o].set == 0) return ;
    	tr[o<<1].set = tr[o<<1|1].set = tr[o].set;
    	tr[o<<1].is = tr[o<<1|1].is = 1;
    	tr[o].set = 0;
    }
    void query(int o, int l, int r, int ql, int qr, int k) {
    	if(tr[o].is) {
    		if(tr[o].set!=0 && !del[tr[o].set]) --ans, ++del_n;//注意判无色
    		del[tr[o].set] = 1;
    		tr[o].set = k/*, tr[o].is = 1*/;
    		return ;
    	}
    	int mid = (l+r)>>1;
    	if(ql <= mid) query(o<<1, l, mid, ql, qr, k);
    	if(mid < qr) query(o<<1|1, mid+1, r, ql, qr, k);//找到区间中颜色唯一的tr,并修改 
    	tr[o].is = 1, tr[o].set = k;
    }
    void optset(int o, int l, int r, int ql, int qr, int k) {
    	if(ql <= l && r <= qr) {query(o, l, r, ql, qr, k); return;}//找到要查询并修改的区间 
    	int mid = (l+r)>>1;
    	pushdown(o);
    	if(ql <= mid) optset(o<<1, l, mid, ql, qr, k);
    	if(mid < qr) optset(o<<1|1, mid+1, r, ql, qr, k);
    }
    
    struct tmp{
    	int l, r;
    	char ab;
    }cmd[MAX];
    int st = MAX, ed = -MAX;
    
    int main() {
    	scanf("%d",&q);
    	for(int i = 1; i <= q; i++) {
    		cin>>cmd[i].ab;
    		if(cmd[i].ab == 'A') {
    			scanf("%d%d",&cmd[i].l, &cmd[i].r);
    			st = min(cmd[i].l, st), ed = max(ed, cmd[i].r);
    		}
    	}
    	build(1, st, ed);
    	int cnt = 0;//颜色序数 
    	for(int i = 1; i <= q; i++) {
    		if(cmd[i].ab == 'A') {
    			++cnt, del_n = 0, ++ans;
    			optset(1, st, ed, cmd[i].l, cmd[i].r, cnt);
    			printf("%d
    ",del_n);
    		} else printf("%d
    ",ans);
    	}
    	return 0; 
    }
    
  • 相关阅读:
    fastjson 使用方法
    算法
    SHA算法
    MD5算法
    kindle推送服务
    DLL劫持
    Hook编程
    Hook技术
    权限验证
    虚拟机
  • 原文地址:https://www.cnblogs.com/tyner/p/11695360.html
Copyright © 2011-2022 走看看