zoukankan      html  css  js  c++  java
  • 题解 P1311 【选择客栈】

    题目只要求合法的方案数

    我们不难发现,如果当前状态合法,那么右端点右面的所有状态也合法。

    先用ST表保证 (O(1)) 算出区间最小值,方便判断当前区间是否有合法的咖啡店,再用vector记录每个色调出现的位置,然后一个色调一个色调的计算,若合法则ans加右指针之后所有的点(包括右指针),同时左指针右移;不合法则右指针右移

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<vector>
    #include<cmath>
    #define N 1000010
    using namespace std;
    int n,k,p,a[N],b[N],f[N][21];
    vector<int>c[51];
    inline void read(int &x)
    {
    	char c;x=0;int f=1;
    	while(!isdigit(c))
    	{
    		if(c=='-')f=-1;
    		c=getchar();
    	}
    	while(isdigit(c))x=x*10+c-'0',c=getchar();
    	x*=f;
    }
    inline void build()
    {
    	for(int i=1;i<=n;++i)f[i][0]=b[i];
    	for(int i=1;i<=20;++i)
    		for(int j=1;j<=n;++j)
    			if(j+(1<<i)-1<=n)
    				f[j][i]=min(f[j][i-1],f[j+(1<<(i-1))][i-1]);
    }
    inline int query(int i,int j){
    	int k=floor(log(j-i+1)/log(2));
    	int ans=min(f[i][k],f[j-(1<<k)+1][k]);
    	return ans;
    }
    int main()
    {
    	read(n),read(k),read(p);
    	for(int i=1;i<=n;++i)
    	{
    		read(a[i]),read(b[i]);
    		c[a[i]].push_back(i);
    	}
    	build();
    	int l=0,r=1,ans=0;
    	for(int i=0;i<k;++i)
    	{
    		l=0,r=1;
    		while(r<c[i].size())
    		{
    			if(l==r)r++;
    			if(r>=c[i].size())break;
    			int minn=query(c[i][l],c[i][r]);
    		//	printf("%d %d %d
    ",minn,c[i][l],c[i][r]);
    			if(minn<=p)
    			{
    				ans+=c[i].size()-r;
    				l++;
    			}
    			else r++;
    			
    		}
    	}
    //	for(int i=0;i<c[1].size();++i)printf("%d ",c[1][i]);
    //	printf("
    ");
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    内置函数(少量)
    画国旗(尺寸不标准)
    测试题——程序
    乱码笔记2--字典
    列表
    课堂笔记 ——————乱
    如何利用pip安装国内镜像源
    pip常用指令
    pip卸载
    pip简介
  • 原文地址:https://www.cnblogs.com/Wuhen-GSL/p/15041665.html
Copyright © 2011-2022 走看看