zoukankan      html  css  js  c++  java
  • 「bzoj3956: Count」

    题目

    刚开始并没有看懂题意于是痛苦的挣扎了好久

    题意是这样的

    ([l,r])有多少对((i,j))满足(a_i)(a_j)恰好是(a_i...a_j)中严格最大的两个数

    强制在线

    先考虑(a_j)(a_i...a_j)严格第二大的那一个

    我们可以一个单调栈扫过去找到(j)之前第一个大于等于(a_j)的,这个位置就是我们要找的(i)

    再考虑(a_j)(a_i...a_j)最大的那一个

    显然如果(i)满足(i<j)(a_j)(a_i)右边第一个满足(a_j>=a_i)的元素就好了

    这样的话最终答案显然是(n)级别的,不会太大,于是直接用单调栈把这些区间都找出来,每次询问([l,r])完全包含了多个这样的区间就好了

    主席树就可以实现

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<set>
    #define mp std::make_pair
    #define maxn 300005
    #define M maxn*42
    #define lowbit(x) ((x)&(-x))
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read()
    {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    typedef std::pair<int,int> pii;
    std::set<pii> s;
    int n,m,q,cnt;
    int st[maxn],top,last,rt[maxn];
    int a[maxn],L[maxn],R[maxn];
    std::vector<int> v[maxn];
    int l[M],r[M],d[M];
    int change(int pre,int x,int y,int pos)
    {
    	int root=++cnt;
    	d[root]=d[pre]+1;
    	if(x==y) return root;
    	l[root]=l[pre],r[root]=r[pre];
    	int mid=x+y>>1;
    	if(pos<=mid) l[root]=change(l[pre],x,mid,pos);
    		else r[root]=change(r[pre],mid+1,y,pos);
    	return root;
    }
    int query(int p1,int p2,int x,int y,int k)
    {
    	if(x==y) return d[p2]-d[p1];
    	int mid=x+y>>1;
    	if(k<=mid) return query(l[p1],l[p2],x,mid,k)+d[r[p2]]-d[r[p1]];
    	return query(r[p1],r[p2],mid+1,y,k);
    }
    int main()
    {
    	n=read(),m=read(),q=read();
    	for(re int i=1;i<=n;i++) a[i]=read();
    	for(re int i=n;i;--i)
    	{
    		while(top&&a[st[top]]<=a[i]) L[st[top--]]=i;
    		st[++top]=i; 
    	}
    	top=0;
    	for(re int i=1;i<=n;i++)
    	{
    		while(top&&a[st[top]]<=a[i]) R[st[top--]]=i;
    		st[++top]=i;
    	}
    	for(re int i=1;i<=n;i++) if(L[i]) s.insert(mp(L[i],i));
    	for(re int i=1;i<=n;i++) if(R[i]) s.insert(mp(i,R[i]));
    	for(std::set<pii>::iterator i=s.begin();i!=s.end();++i)
    	{
    		pii t=*i;
    		v[t.second].push_back(t.first);
    	}
    	for(re int i=1;i<=n;i++)
    	{
    		int now=rt[i-1];
    		for(re int j=0;j<v[i].size();j++) now=change(now,1,n,v[i][j]);
    		rt[i]=now;
    	}
    	int x,y;
    	while(m--)
    	{
    		x=read(),y=read();
    		if(q) x=(x+last-1)%n,y=(y+last-1)%n,x++,y++;
    		if(x>y) std::swap(x,y);
    		if(x==y) last=0;
    		else last=query(rt[x-1],rt[y],1,n,x);
    		printf("%d
    ",last);
    	}
    	return 0;
    }
    
  • 相关阅读:
    [HNOI2002]营业额统计
    HDU 1374
    HDU 3345
    HDU 2089
    Graham扫描法
    Codeforces 1144D Deduction Queries 并查集
    Codeforces 916E Jamie and Tree 线段树
    Codeforces 1167F Scalar Queries 树状数组
    Codeforces 1167E Range Deleting
    Codeforces 749E Inversions After Shuffle 树状数组 + 数学期望
  • 原文地址:https://www.cnblogs.com/asuldb/p/10362232.html
Copyright © 2011-2022 走看看