zoukankan      html  css  js  c++  java
  • Loj3033 JOISC 2019 Day2两个天线

    Loj3033 JOISC 2019 Day2两个天线

    下午唯一听懂的题目但,但还是比较模糊.写一篇题解来加深一下印象.
    题目大意:给定(n)根天线,第(i)跟天线的高度为(h_i),切它能和与他距离在([a_i,b_i])内的天线交流.
    两根天线互相交流当且仅当他们彼此都在对方的交流范围内.定义两根天线交流的代价为(|H_i-H_j|)
    (Q)次询问,每次询问区间([l,r])内所有够相互交流的天线的交流代价的最大值((n <= 2*10^5))

    首先看到这种东西,我的第一反应是CDQ分治,但是CDQ分治不好处理这种多组区间询问的问题
    所以只能另想办法
    发现如果我们对于每个(j),都去寻找前面的一个(i)去和它匹配的话.那么(j)(i)的影响范围内当且仅当(jin[i+a_i,i+b_i])
    也就是说,我们要想办法让(i)(i+a_i)处开始有贡献,在(i + b_i + 1)处失去贡献.这就会想到线段树扫描线,我们每个节点维护一个(c_i),当我们枚举到(i+a_i)时,就讲线段树上第(i)个位置的(c_i)变为(h_i),当离开这个区间时,就将其变为(-infty)
    这样我们就处理好了第一个问题:如何确保(j)(i)的交流范围内
    接下来看第二个问题,如何确保(i)(j)的范围内并且统计答案
    首先,(|h_i-h_j|)这个东西,我们可以讲它拆成(h_i-h_j)(h_j-h_i)就好了我们只考虑(h_i-h_j),另一个可以将值域翻转来考虑.
    那么我们设(d_i)表示第(i)的天线和右边的匹配的最大代价这个东西可以直接在线段树上维护
    而.(di=h_i+max(-h_j))
    那么我们对于每个(j),它能影响的之前的区间是([i - b_i,i-a_i])(特判一下负数)
    我们在在线段树上维护一个(tag),表示(max(-hj))
    那么扫到(j)时,就相当于在([i - b_i,i-a_i])(tag)(-h_j)取max,这也是线段树能完成的
    最后对于每个查询,扫到(r_i)时计算([l_i,r_i])的答案就好了
    (SB的我(n,m)不分WA了一晚上)

    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<cctype>
    #include<algorithm>
    #define pii pair<int,int>
    #define mk make_pair
    using namespace std;
    const int N = 5e5 + 3;
    const int INF = 1e9 + 7;
    int n,m,t;
    struct node{
    	int lc,rc;
    	int d,c,tag;	
    }a[N << 1];
    struct U{
    	int hi;
    	int ai,bi;	
    }b[N];
    struct Q{
    	int li,ri;	
    }q[N];
    int ans[N];
    vector <pii> G1[N];
    vector <int> G2[N];
    inline int read(){
        int v = 0,c = 1;char ch = getchar();
        while(!isdigit(ch)){
            if(ch == '-') c = -1;
            ch = getchar();
        }
        while(isdigit(ch)){
            v = v * 10 + ch - 48;
            ch = getchar(); 
        }
        return v * c;
    }
    inline void pushup(int u){
    	a[u].c = max(a[a[u].lc].c,a[a[u].rc].c);
    	a[u].d = max(a[a[u].lc].d,a[a[u].rc].d);	
    }
    inline void build(int u,int l,int r){
    	a[u].c = a[u].d = a[u].tag = -INF;
    	if(l == r) return ;
    	int mid = (l + r) >> 1;
    	a[u].lc = ++t;build(a[u].lc,l,mid);
    	a[u].rc = ++t;build(a[u].rc,mid + 1,r);
    //	pushup(u);
    }
    inline void pushdown(int u,int l,int r){
    	if(a[u].tag == -INF) return;
    	a[a[u].lc].tag = max(a[a[u].lc].tag,a[u].tag);
    	a[a[u].rc].tag = max(a[a[u].rc].tag,a[u].tag);
    	a[a[u].lc].d = max(a[a[u].lc].d,a[a[u].lc].c + a[a[u].lc].tag);
    	a[a[u].rc].d = max(a[a[u].rc].d,a[a[u].rc].c + a[a[u].rc].tag);
    	a[u].tag = -INF;
    }
    inline void change(int u,int l,int r,int x,int v){
    	if(l == r){
    		a[u].tag = -INF;
    		a[u].c = v;
    		//a[u].d = max
    		return;
    	}
    	pushdown(u,l,r);
    	int mid = (l + r) >> 1;
    	if(x <= mid) change(a[u].lc,l,mid,x,v);
    	else change(a[u].rc,mid + 1,r,x,v);
    	pushup(u);
    }
    inline void updata(int u,int l,int r,int ll,int rr,int v){
    	if(l == ll && r == rr){
    		a[u].tag = max(a[u].tag,v);
    		a[u].d = max(a[u].d,a[u].c + a[u].tag);
    		return ;
    	}
    	pushdown(u,l,r);
    	int mid = (l + r) >> 1;
    	if(rr <= mid) updata(a[u].lc,l,mid,ll,rr,v);
    	else if(ll > mid) updata(a[u].rc,mid + 1,r,ll,rr,v);
    	else {
    		updata(a[u].lc,l,mid,ll,mid,v);
    		updata(a[u].rc,mid + 1,r,mid + 1,rr,v);	
    	}
    	pushup(u);
    }
    inline int query(int u,int l,int r,int ll,int rr){
    	if(l == ll && r == rr) return a[u].d;	
    	pushdown(u,l,r);
    	int mid = (l + r) >> 1;
    	if(rr <= mid) return query(a[u].lc,l,mid,ll,rr);
    	else if(ll > mid) return query(a[u].rc,mid + 1,r,ll,rr);
    	else return max(query(a[u].lc,l,mid,ll,mid),
    	query(a[u].rc,mid + 1,r,mid + 1,rr));
    }
    inline void work(){
    	t = 1;
    	build(1,1,n);	
    	for(int i = 1;i <= n;++i){
    		for(int j = 0;j < G1[i].size();++j)
    		change(1,1,n,G1[i][j].first,G1[i][j].second?b[G1[i][j].first].hi:-INF);
    		if(i - b[i].ai > 0) updata(1,1,n,max(1,i - b[i].bi),i - b[i].ai,-b[i].hi);
    		for(int j = 0;j < G2[i].size();++j)
    		ans[G2[i][j]] = max(ans[G2[i][j]],query(1,1,n,q[G2[i][j]].li,q[G2[i][j]].ri));
    	}
    }
    int main(){
    	n = read();
    	for(int i = 1;i <= n;++i){
    		b[i].hi = read(),b[i].ai = read(),b[i].bi = read();
    		if(i + b[i].ai <= n) G1[i + b[i].ai].push_back(mk(i,1));
    		if(i + b[i].bi + 1 <= n) G1[i + b[i].bi + 1].push_back(mk(i,0));
    	}
    	m = read();
    	for(int i = 1;i <= m;++i){
    		q[i].li = read();
    		q[i].ri = read();
    		G2[q[i].ri].push_back(i);	
    	}
    	for(int i = 1;i <= m;++i) ans[i] = -1;
    	work();
    //		for(int i = 1;i <= n;++i) printf("%d
    ",ans[i]);
    	for(int i = 1;i <= n;++i) b[i].hi = 1000000001 - b[i].hi;
    	work();
    	for(int i = 1;i <= m;++i) printf("%d
    ",ans[i]);
    	return 0;	
    }
    
  • 相关阅读:
    记一个SharePoint Workflow一睡永不醒来的问题
    .NET Tracing简介
    !aspxpages(即!dumphttpcontext)命令输出的解释
    MOSS定时爬网无法启动的问题
    Persistent cookies和Session cookies的定义与区别
    跨SharePoint服务器场的Content Deployment的一个知识点
    如何明确指定命令所在的debugger extension?
    理解SharePoint中的备用访问映射(Alternate Access Mapping)
    biztalk中ACK、NACK详测示例【转】
    深入biztalk消息以及消息订阅发布路由机制(一)-消息概述【转】
  • 原文地址:https://www.cnblogs.com/wyxdrqc/p/10956010.html
Copyright © 2011-2022 走看看