• 「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;
    }
    
  • 相关阅读:
    初探WebService
    【前端】CSS3实现弹出效果
    html转pdf、html页面保存为word文件、将页面上的table表格导出为excel
    DES64位加密解密
    xml文件数据上报——根据模型生成对应的xml文件进行上报
    数据上报-动态生成winform表单
    图片轮播 及通知公告上滚动 (无空隙滚动)
    jQuery 全选与不全选 Jquery each
    webform快速创建表单内容文件--oracle 数据库
    Ajax 通过post提交数据到一般处理程序,后台快速获取数据的方法
  • 原文地址:https://www.cnblogs.com/asuldb/p/10362232.html
Copyright © 2020-2023  润新知