zoukankan      html  css  js  c++  java
  • [AH2017/HNOI2017]影魔

    传送门

    题面涉嫌抄袭dota2

    这个题好巧妙啊……
    首先我们预处理出对于每个点,在它左边和右边最靠近他的并且大于它的点在哪,这个可以用单调栈做。小声bb一句其实这玩意也可以用主席树,值域这么小是为这个准备的?
    然后每个(l[i],r[i])会产生一个p1的贡献,而对于(l[i]),在([i+1,r[i]-1])区间中的点每个都会产生一个p2的贡献,对于(r[i]),在([l[i]+1,i-1])中每个点会产生一个p2的贡献.
    啊,然后我们就可以离线去做了……每次在扫到(l[i],r[i])的时候对应的在线段树上进行修改……
    然后我们把每个询问区间都离线下来,对于每个区间([l,r]),在扫到l-1的时候,我们减去当前这段区间的值,在扫到r的时候再加上,就可以得到这段区间的答案了。

    借用老詹的话,区间排序用啥排序,用vector存下来是真的爽。

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    #define pb push_back
    
    using namespace std;
    typedef long long ll;
    const int M = 200005;
    const int mod = 1e9+7;
    
    ll read()
    {
       ll ans = 0,op = 1;char ch = getchar();
       while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
       while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
       return ans * op;
    }
    
    struct tree
    {
       ll sum,lazy;
    }t[M<<2];
    
    struct dot
    {
       ll l,r;
    }d[M<<1];
    
    struct node
    {
       int id,fla;
    };
    
    vector<node> v[M],q[M];
    ll n,m,p1,p2,k[M],sta[M],top,l,r,ans[M];
    
    void init()
    {
       rep(i,1,n)
       {
          while(top && k[sta[top]] < k[i]) top--;
          d[i].l = sta[top],sta[++top] = i;
       }
       top = 0,sta[top] = n + 1;
       per(i,n,1)
       {
          while(top && k[sta[top]] < k[i]) top--;
          d[i].r = sta[top],sta[++top] = i;
       }
       rep(i,1,n) v[d[i].l].pb((node){i,0}),v[d[i].r].pb((node){i,1});
    }
    
    void pushdown(int p,int l,int r)
    {
       int mid = (l+r) >> 1;
       if(t[p].lazy)
       {
          t[p<<1].lazy += t[p].lazy,t[p<<1|1].lazy += t[p].lazy;
          t[p<<1].sum += t[p].lazy * (mid - l + 1);
          t[p<<1|1].sum += t[p].lazy * (r - mid);
          t[p].lazy = 0;
       }
    }
    
    void modify(int p,int l,int r,int kl,int kr,ll val)
    {
       if(kl > kr) return;
       if(l == kl && r == kr) {t[p].sum += val * (r - l + 1),t[p].lazy += val;return;}
       int mid = (l+r) >> 1;
       pushdown(p,l,r);
       if(kr <= mid) modify(p<<1,l,mid,kl,kr,val);
       else if(kl > mid) modify(p<<1|1,mid+1,r,kl,kr,val);
       else modify(p<<1,l,mid,kl,mid,val),modify(p<<1|1,mid+1,r,mid+1,kr,val);
       t[p].sum = t[p<<1].sum + t[p<<1|1].sum;
    }
    
    ll query(int p,int l,int r,int kl,int kr)
    {
       if(l == kl && r == kr) return t[p].sum;
       int mid = (l+r) >> 1;
       pushdown(p,l,r);
       if(kr <= mid) return query(p<<1,l,mid,kl,kr);
       else if(kl > mid) return query(p<<1|1,mid+1,r,kl,kr);
       else return query(p<<1,l,mid,kl,mid) + query(p<<1|1,mid+1,r,mid+1,kr);
    }
    
    int main()
    {
       n = read(),m = read(),p1 = read(),p2 = read();
       rep(i,1,n) k[i] = read();
       init();
       rep(i,1,m)
       {
          l = read(),r = read(),d[i + n] = (dot){l,r};
          q[l-1].pb((node){i,-1}),q[r].pb((node){i,1});
       }
       rep(i,1,n)
       {
          rep(j,0,(int)v[i].size()-1)
          {
    	 int cur = v[i][j].id,fla = v[i][j].fla;
    	 if(!fla) modify(1,1,n,cur+1,d[cur].r-1,p2);
    	 else
    	 {
    	    if(d[cur].l) modify(1,1,n,d[cur].l,d[cur].l,p1);
    	    modify(1,1,n,d[cur].l+1,cur-1,p2);
    	 }  
          }
          rep(j,0,(int)q[i].size()-1)
          {
    	 int cur = q[i][j].id;
    	 ans[cur] += query(1,1,n,d[cur+n].l,d[cur+n].r) * q[i][j].fla;
          }
       }
       rep(i,1,m) ans[i] += p1 * (d[i+n].r - d[i+n].l);
       rep(i,1,m) printf("%lld
    ",ans[i]);
       return 0;
    }
    
    
  • 相关阅读:
    WPF 基础
    设计模式
    设计模式
    设计模式
    设计模式
    设计模式
    设计模式
    【DFS】hdu 1584 蜘蛛牌
    【优先队列】hdu 1434 幸福列车
    【最长公共子序列】hdu 1243 反恐训练营
  • 原文地址:https://www.cnblogs.com/captain1/p/10604691.html
Copyright © 2011-2022 走看看