zoukankan      html  css  js  c++  java
  • [2021.8集训Day10/JZOJ.3441]【NOIP2013模拟】小喵喵的新家

    [2021.8集训Day10/JZOJ.3441]【NOIP2013模拟】小喵喵的新家

    题目

    思路

    线段树.

    为了方便,我们将题目中提到的最小的扇形,即圆心角为(frac {2pi}{2m})的扇形,叫做"单位扇形".

    注意题目说的是:

    她想知道有多大面积被至少铺过k次地毯

    所以,我们把每一次操作,按照半径从大到小排序.依次枚举,当枚举到(i)时,一个"单位扇形"恰好被覆盖(k)次,不论后面再覆盖,这个半径为(r_i)单位扇形总会被算进答案.

    我们把每一个单位扇形抽象成一个个区间,用线段树维护即可.

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    int read() {
    	int re = 0;
    	char c = getchar();
    	bool negt = false;
    	while(c < '0' || c > '9')
    		negt |= (c == '-') , c = getchar();
    	while(c >= '0' && c <= '9')
    		re = (re << 1) + (re << 3) + c - '0' , c = getchar();;
    	return negt ? -re : re;
    }
    
    int max(int a , int b) {
    	return a > b ? a : b;
    }
    
    const int inf = 0x3fffffff;
    template <int ArraySize>
    class SegmentTree {
    #define ls(_) node[p].ls
    #define rs(_) node[p].rs
    	private :
    		struct NodeClass {
    			int l , r , ls , rs , tag;
    			int maxnum , radius;
    		} node[ArraySize];
    	public :
    		int newnode () {
    			static int cnt = 0;
    			++cnt;
    		}
    		int build(int l , int r , int ori_data) {
    			int id = newnode();
    			node[id].l = l , node[id].r = r , node[id].maxnum = ori_data;
    			int mid = (l + r) / 2;
    			if(l == r)
    				return id;
    			node[id].ls = build(l , mid , ori_data);
    			node[id].rs = build(mid + 1 , r , ori_data);
    			return id;
    		}
    		void push_down(int p) {
    			if(node[p].tag != 0) {
    				node[ls(p)].maxnum += node[p].tag;
    				node[ls(p)].tag += node[p].tag;
    				node[rs(p)].maxnum += node[p].tag;
    				node[rs(p)].tag += node[p].tag;
    				node[p].tag = 0;
    			}
    		}
    		void change(int p , int l , int r , int radius) {
    			if(r < node[p].l || l > node[p].r)
    				return ;
    			if(node[p].maxnum == -1) {//加上这次覆盖后,有新的单位扇形被覆盖k次,不论区间是否全覆盖,强制下传,这里最多执行2m次,每次是log级别,不会超时
    				if(node[p].l == node[p].r)
    					node[p].radius = radius , node[p].maxnum = -inf;//为了方便,maxnum赋值无穷小
    				else {
    					push_down(p);
    					change(ls(p) , l , r , radius);
    					change(rs(p) , l , r , radius);
    					node[p].maxnum = max(node[ls(p)].maxnum , node[rs(p)].maxnum);
    				}
    				return;
    			}
    			if(l <= node[p].l && r >= node[p].r) {
    				node[p].maxnum += 1 , node[p].tag += 1;
    				return ;
    			}
    			push_down(p);
    			change(ls(p) , l , r , radius);
    			change(rs(p) , l , r , radius);
    			node[p].maxnum = max(node[ls(p)].maxnum , node[rs(p)].maxnum);
    		}
    		int query_radius(int p , int pos) {
    			if(node[p].l == node[p].r)
    				return node[p].radius;
    			int mid = (node[p].l + node[p].r) / 2;
    			push_down(p);
    			return pos <= mid ? query_radius(ls(p) , pos) : query_radius(rs(p) , pos);
    		}
    		int query_maxnum(int p , int pos) {
    			if(node[p].l == node[p].r)
    				return node[p].maxnum;
    			int mid = (node[p].l + node[p].r) / 2;
    			push_down(p);
    			return pos <= mid ? query_maxnum(ls(p) , pos) : query_maxnum(rs(p) , pos);
    		}
    #undef ls
    #undef rs
    };
    
    typedef long long lint ;
    const int N = 200000 , M = 100000;
    
    struct Draw {
    	int s , t , r;
    } d[N + 10];
    bool cmp(Draw a , Draw b) {
    	return a.r > b.r;
    }
    
    int n , m , k;
    int root;
    SegmentTree <M * 2 * 4 + 10> SegT;
    
    signed main() {
    //	freopen("data//newhome13.in" , "r" , stdin);
    
    	n = read() , m = read() , k = read();
    
    	int n1 = n;
    	for(int i = 1 ; i <= n ; i++) {
    		d[i].r = read() , d[i].s = read() , d[i].t = read();
    		if(d[i].s < d[i].t)
    			d[i].s += m , d[i].t += m - 1;
    		else {
    			
    			++n1;
    			d[n1].r = d[i].r , d[n1].s = -m + m , d[n1].t = d[i].t + m - 1;
    			d[i].s += m ,  d[i].t = m + m - 1;
    		}
    	}
    	n = n1;
    
    	std::sort(d + 1 , d + n + 1 , cmp);
    	root = SegT.build(0 , m * 2 , -k);
    
    	for(int i = 1 ; i <= n ; i++) {
    		if(d[i].s <= d[i].t)
    			SegT.change(root , d[i].s , d[i].t , d[i].r);
    	}
    
    	lint ans = 0;
    	for(int i = 0 ; i < m * 2 ; i++) {
    		lint r = SegT.query_radius(root , i);
    		ans += r * r ;
    //		std::cout << SegT.query_radius(root , i) << '
    ';
    	}
    	std::cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    用 Go 实现一个 LRU cache
    【转】入行软件测试,零基础拿OFFER
    【转】IntelliJ idea 高效使用教程,一劳永逸!
    python连接Oracle报错DPI1047
    【转】Pycharm快捷键设置(鼠标滚动控制字体大小)
    【转】Ubuntu:命令行安装可视化界面
    【转】Windows 如何在cmd命令行中查看、修改、删除与添加环境变量
    VAR多变量预测
    windows进程管理
    git关闭filemode
  • 原文地址:https://www.cnblogs.com/dream1024/p/15168160.html
Copyright © 2011-2022 走看看