zoukankan      html  css  js  c++  java
  • [HNOI2016] 序列

    题面

        一看可以离线果断上扫描线,然后再开一颗线段树,叶子 i 记录 右端点<=目前扫描线右端点,左端点在i的所有区间的最小值之和。

        然后直接扫描就行了,需要开个单调栈维护更新线段树的过程。复杂度玄学,全看数据。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    #define pb push_back
    #define lc (o<<1)
    #define mid (l+r>>1)
    #define rc ((o<<1)|1) 
    const int N=1e5+5;
    
    inline int read(){
        int x=0,f=1; char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x*f;
    }
    
    void W(ll x){ if(x>=10) W(x/10); putchar(x%10+'0');}
    
    struct node{ int l,num;};
    vector<node> ask[N];
    int s[N],tp,n,a[N],le,ri,w,Q,len[N*4];
    ll tag[N*4],sum[N*4],ans[N],*now;
    
    void build(int o,int l,int r){
    	len[o]=r-l+1;
    	if(l==r) return;
    	build(lc,l,mid),build(rc,mid+1,r);
    }
    
    inline void Get(int x,ll W){
    	tag[x]+=W,sum[x]+=W*(ll)len[x];
    }
    
    inline void pd(int o){
    	Get(lc,tag[o]),Get(rc,tag[o]),tag[o]=0;
    }
    
    void update(int o,int l,int r){
    	if(l>=le&&r<=ri){ Get(o,w); return;}
    	pd(o);
    	if(le<=mid) update(lc,l,mid);
    	if(ri>mid) update(rc,mid+1,r);
    	sum[o]=sum[lc]+sum[rc];
    }
    
    void query(int o,int l,int r){
    	if(l>=le&&r<=ri){ *now+=sum[o]; return;}
    	pd(o);
    	if(le<=mid) query(lc,l,mid);
    	if(ri>mid) query(rc,mid+1,r);
    }
    
    inline void Geng(int p){
    	while(tp&&a[p]<=a[s[tp]]) tp--;
    	s[++tp]=p;
    	
    	for(int i=1;i<=tp;i++) le=s[i-1]+1,ri=s[i],w=a[s[i]],update(1,1,n);
    }
    
    inline void solve(){
    	for(int i=1;i<=n;i++){
            Geng(i);
            for(node u:ask[i]) now=ans+u.num,le=u.l,ri=i,query(1,1,n);
    	}
    }
    
    int main(){
    	n=read(),Q=read(),a[0]=-(1<<30);
    	for(int i=1;i<=n;i++) a[i]=read();
    	for(int i=1;i<=Q;i++) le=read(),ri=read(),ask[ri].pb((node){le,i});
    	build(1,1,n),solve();
    	for(int i=1;i<=Q;i++){
    		if(ans[i]<0) ans[i]=-ans[i],putchar('-');
    	    W(ans[i]),puts("");
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    正交实验
    边界值
    等价类划分概述
    测试用例编写
    java基础复习(四)
    easyui datagrid 搜索功能
    一段代码把网站变成灰白色
    PHP 获取二维数组中某个key的集合
    如何使用Mobile_Detect来判断访问网站的设备:安卓,平板,电脑
    easyui validatebox 验证类型
  • 原文地址:https://www.cnblogs.com/JYYHH/p/11304373.html
Copyright © 2011-2022 走看看