// 基本数据结构-栈

1 篇文章 0 订阅
1 篇文章 0 订阅

链接:https://ac.nowcoder.com/acm/contest/1005/A
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述

You are going to implement the most powerful editor for integer sequences.
The sequence is empty when the editor is initialized.
There are 5 types of instructions.

I x Insert x after the cursor.
D Delete the element before the cursor.
L Move the cursor left unless it has already been at the begin.R Move the cursor right unless it has already been at the end.
Q k Suppose that the current sequence BEFORE the cursor is {a1,a2…an}\{ a_1,a_2\dots a_n \}{a1​,a2​…an​}. Find max1≤i≤kSimax_{1\leq i\leq k} S_imax1≤i≤k​Si​ where  S;=a1+a2+⋅⋅+a¡S_; = a_1 +a_2+··+ a_¡S;​=a1​+a2​+⋅⋅+a¡​

输入描述:

The input file consists of multiple test cases. For each test case:
The first line contains an integer Q, which is the number of instructions. The next Q lines contain an instruction asdescribed above.
(1<Q<1061 \lt Q \lt 10^61<Q<106,∣x[<103|x[ \lt10^3∣x[<103 for I instruction, 1<k<n1 \lt k\lt n1<k<n. for Q instruction)

输出描述:

For each Q instruction, output the desired value.

示例1
输入
复制

8
I 2
I -1
I 1
Q 3
L
D
R
Q 2

输出
复制

2
3

说明

The following diagram shows the status of sequence after each instruction:

C464-1004-2.jpg

备注:

1≤Q≤1061 \leq Q \leq 10^61≤Q≤106
∣x∣≤103|x| \leq 10^3∣x∣≤103
1≤k≤n1 \leq k \leq n1≤k≤n

-> LINK

  • 开两个栈 a[]维护的是从开头到光标前的数据 b[]维护的是从光标后到结尾的数据 栈顶都是靠近光标的一端
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int sum[N],ans[N],a[N],b[N];
int main()
{ 
	int m;scanf("%d",&m);
	int l=0,r=0,x;
	ans[0]=-1010;
	while(m--)
	{
		char c[3];scanf("%s",c);
		if(c[0]=='I')
		{
			scanf("%d",&x);
			a[++l]=x;
			sum[l]=sum[l-1]+x;
			ans[l]=max(ans[l-1],sum[l]);
		}
		if(c[0]=='D')
		{
			if(l) l--;
		}
		if(c[0]=='R')
		{
			if(!r)
			{
				continue;
			}
			a[++l]=b[r];
			r--;
			sum[l]=sum[l-1]+a[l];
			ans[l]=max(ans[l-1],sum[l]);
		}
		if(c[0]=='L')
		{
			if(!l)
			{
				continue;
			}
			b[++r]=a[l];
			l--;
		}
		if(c[0]=='Q')
		{
			scanf("%d",&x);
			printf("%d\n",ans[x]);
	    }
	}
}

链接:https://ac.nowcoder.com/acm/contest/1005/C
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles:

Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.
输入描述:

The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that 1≤n≤1000001 \leq n \leq 1000001≤n≤100000. Then follow n integers h1…hnh1\dots hnh1…hn, where 0≤hi≤10000000000 \leq h_i \leq 10000000000≤hi​≤1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1. A zero follows the input for the last test case.

输出描述:

For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.

示例1
输入
复制

7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0

输出
复制

8
4000

说明

Huge input, scanf is recommended.

  • 维护一个高度递增的栈(中间凸出来的部分对之后是没有影响的)
  • w表示这个高度的矩形最多可以向左边延伸多长的距离

LINK

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
typedef long long ll;
ll h[N],st[N],w[N];
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		if(n==0) return 0;int now=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%lld",&h[i]);
		}
		ll ans=0;h[n+1]=0;
	    for(int i=1;i<=n+1;i++)
	    {
	    	ll l=0;
	    	while(h[now]>h[i])
	    	{
	    		l+=w[now];
	    		ans=max(ans,1ll*h[now]*(l));now--;
			}
			h[++now]=h[i];w[now]=1ll+l;
			
		}
		printf("%lld\n",ans);
	}
}

LINK-> ACw

  • 车站示意如图:

          出站<——    <——进站
                   |车|
                   |站|
                   |__|
    

现在请你按《字典序》输出前20种可能的出栈方案。

  • dfs 大概就是枚举每个部分的状态 out表示出战部分,sta表示在栈 的部分 ,rest表示还没入栈的部分
  • 早出栈的字典序一定比较小
#include<bits/stdc++.h>
using namespace std;
vector<int>out;
int rest,cnt=0,n;
stack<int>st;
void dfs()
{
    if(cnt>=20) return ;
    if(out.size()==n)
    {
        ++cnt;
        for(int i=0;i<n;i++)
        {
            cout<<out[i];
        }cout<<endl;
    }
    if(st.size())
    {
        out.push_back(st.top());
        st.pop();
        dfs();
        st.push(out.back());
        out.pop_back();
    }
    if(rest<=n)
    {
        st.push(rest);
        rest++;
        dfs();
        rest--;
        st.pop();
    }
}
int main()
{
    cin>>n;
    rest=1;
    dfs();
}

链接:https://ac.nowcoder.com/acm/contest/1005/B
来源:牛客网

进出栈序列问题
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
一列火车n节车厢,依次编号为1,2,3,…,n。每节车厢有两种运动方式,进栈与出栈,问n节车厢出栈的可能排列方式有多少种。
输入描述:

一个数,n(n≤60000)n (n \leq 60000)n(n≤60000)

输出描述:

一个数s表示n节车厢出栈的可能排列方式

LINK<好艰难诶>

  • 高精度x卡特兰数(C(n ,2n)/(n+1)) 数学+++++
  • 首先知道这是卡特兰数的模型
  • 答案就是C(n,2n)/(n+1)
  • ->也就是(2n)!/[(n!*n!) (n+1)]
  • 对于组合数如果单方面的考虑处理分子/分母 数的范围很大 很可能会超时->考虑分解质因数
  • 举个例子
  • 组合数C(3,6)=(6 * 5 * 4)/(3 * 2 * 1)=>2^ 2 * 3^ 0 * 5^ 1
  • 也就是考虑(2n)!里面有 2的x1次 ,3的x2次,5的几次…以及(n)!里面有 2的y1次 ,3的y2次,5的几次…
  • 答案就应该是[2^(x1-2*y1) * 3 ^(x2-y2 * 2)…]/(n+1)
  • ------------<为什么y1 ,y2要乘2,因为分母是n! * n!>
  • 这里的小知识 关于求n!里面的2的几次之类就是下面的get函数了

[n/2]+[n/(2 * 2 )]+[n/(2 * 2 * 2)]…括号下取整
类似求n!有p的几次[n/p]+[n/(p* p )]+[n/(p * p * p)]…括号下取整

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=120010;
int prime[N],cnt;bool st[N];ll power[N];
void getpr(int n)//筛素数
{
	for(int i=2;i<=n;i++)
	{
		if(!st[i])
		{
			prime[cnt++]=i;
			for(int j=i*2;j<=n;j+=i)
			{
				st[j]=true;
			}
		}
	}
}
int get(int n,int p)//判n!里面有p的几次
{
	int s=0;
	while(n)
	{
		s+=n/p;
		n/=p;
	}return s;
}
void multi(vector<ll>&a,int b)//高精度
{
	ll  t=0;
	for(int i=0;i<a.size();i++)
	{
		a[i]=1ll*a[i]*b+t;
		t=a[i]/1000000000;
		a[i]%=1000000000;
	}
	while(t)
	{
		a.push_back(t%1000000000);
		t/=1000000000;
	}
}
void out(vector<ll>&a)
{
	printf("%lld",a.back());
	for(int i=a.size()-2;i>=0;i--)
	{
		printf("%09lld",a[i]);//压位
	}
	puts("");
}

int main()
{
    int n;
	scanf("%d",&n);
	getpr(n*2);
	for(int i=0;i<cnt;i++)
	{
		int p=prime[i];
		power[p]=get(n*2,p)-get(n,p)*2;
	}
	int k=n+1;//考虑解决剩下的除数n+1
	for(int i=0;i<cnt&&prime[i]<=k;i++)
	{
		int p=prime[i],s=0;
		while(k%p==0)
		{
			s++;
			k/=p;
		}power[p]-=s;
	} 
	vector<ll>res;
	res.push_back(1ll);
	for(int i=2;i<=n*2;i++)
	{
		for(int j=0;j<power[i];j++)
		{
			multi(res,i);
		}
	}
	out(res);
	
}

T掉的码 ~~

#include<cstdio>
using namespace std;
const int N=600010;
typedef long long ll;
ll tt,ans[N];
inline void multi(int b)
{
	ll t=0;
	for(register int i=0;i<=tt;i++)
	{
		ans[i]=ans[i]*b+t;
		t=ans[i]/1000000000;
		ans[i]%=1000000000;
	}
	while(t)
	{
		ans[++tt]=t%1000000000;
		t/=1000000000;
	}
}
inline void div(int b)
{
	ll t=0;
	for(register int i=tt;i>=0;i--)
	{
		ans[i]+=t*1000000000;
		t=ans[i]%b;
		ans[i]/=b;
	}
	while(ans[tt]==0)
	{
		tt--;
	}
}
int main()
{
	static int n;scanf("%d",&n);
	tt=0;
	ans[0]=1ll;
	for(register int i=n*2,j=1;j<=n;++j,--i)
	{
		multi(i);
		div(j);
	}div(n+1);
	printf("%lld",ans[tt]);
	for(register int i=tt-1;i>=0;i--)
	{
		printf("%09lld",ans[i]);
	}
	puts("");
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值