#include
using namespace std;
const int N = 100010;
// head 表示头结点的下标
// e[i] 表示节点i的值
// ne[i] 表示节点i的next指针是多少
// idx 存储当前已经用到了哪个点
int head, e[N], ne[N], idx;
// 初始化
void init()
{
head = -1;
idx = 0;
}
// 将x插到头结点
void add_to_head(int x)
{
e[idx] = x, ne[idx] = head, head = idx ++ ;
}
// 将x插到下标是k的点后面
void add(int k, int x)
{
e[idx] = x, ne[idx] = ne[k], ne[k] = idx ++ ;
}
// 将下标是k的点后面的点删掉
void remove(int k)
{
ne[k] = ne[ne[k]];
}
int main()
{
int m;
cin >> m;
init();
while (m -- )
{
int k, x;
char op;
cin >> op;
if (op == 'H')
{
cin >> x;
add_to_head(x);
}
else if (op == 'D')
{
cin >> k;
if (!k) head = ne[head];
else remove(k - 1);
}
else
{
cin >> k >> x;
add(k - 1, x);
}
}
for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' ';
cout << endl;
return 0;
}
#include
using namespace std;
const int N = 100010;
int m;
int e[N], l[N], r[N], idx;
// 在节点a的右边插入一个数x
void insert(int a, int x)
{
e[idx] = x;
l[idx] = a, r[idx] = r[a];
l[r[a]] = idx, r[a] = idx ++ ;
}
// 删除节点a
void remove(int a)
{
l[r[a]] = l[a];
r[l[a]] = r[a];
}
int main()
{
cin >> m;
// 0是左端点,1是右端点
r[0] = 1, l[1] = 0;
idx = 2;
while (m -- )
{
string op;
cin >> op;
int k, x;
if (op == "L")
{
cin >> x;
insert(0, x);
}
else if (op == "R")
{
cin >> x;
insert(l[1], x);
}
else if (op == "D")
{
cin >> k;
remove(k + 1);
}
else if (op == "IL")
{
cin >> k >> x;
insert(l[k + 1], x);
}
else
{
cin >> k >> x;
insert(k + 1, x);
}
}
for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << ' ';
cout << endl;
return 0;
}
#include
#include
#include
#include
#include
using namespace std;
stack<int> num;
stack<char> op;
void eval()
{
auto b=num.top();num.pop();
auto a=num.top();num.pop();
auto c=op.top();op.pop();
int x;
if(c=='+') x=a+b;
else if(c=='-') x=a-b;
else if(c=='*') x=a*b;
else x=a/b;
num.push(x);
}
int main()
{
unordered_map<char,int> pr{{'-',1},{'+',1},{'*',2},{'/',2}};
string str;
cin>>str;
for(int i=0;str[i];i++)
{
auto c=str[i];
if(isdigit(c))
{
int x=0,j=i;
while(j<str.size()&&isdigit(str[j])) x=x*10+str[j++]-'0';
i=j-1;
num.push(x);
}
else if(c=='(') op.push(c);
else if(c==')')
{
while(op.top()!='(') eval();
op.pop();
}
else
{
while(op.size()&&op.top()!='('&&pr[op.top()]>=pr[c]) eval();
op.push(c);
}
}
while(op.size()) eval();
cout<<num.top()<<endl;
return 0;
}
#include
#include
using namespace std;
const int N=1e5+10;
int stk[N];
int tt=0;
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
while(tt&&stk[tt]>=x) tt--;
if(tt) printf("%d ",stk[tt]);
else printf("-1 ");
stk[++tt]=x;
}
return 0;
}
保证每次存放与窗口大小相等的元素。
时间复杂度o(nk) 含有的元素个数n,窗口大小k。
#include
#include
using namespace std;
const int N=1e6+10;
//a是数据 q是队列,队列中存储的是下标
int a[N],q[N];
int main()
{
//n数据量 k滑动窗口大小
int n,k;
scanf("%d%d",&n,&k);
int hh=0,tt=-1;
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<n;i++)
{
//判断队列是否已经滑出了窗口
//队列中存储的是下标
//右端点是i 左端点是i-k+1 如果大于->滑出窗口
//出队
if(hh<=tt&&i-k+1>q[hh]) hh++;
//当前插入的值a[i]比队尾(a[q[tt]])的值要小 队尾出队
while(hh<=tt&&a[q[tt]]>=a[i]) tt--;
//插入新元素
q[++tt]=i;
//对于前k个数求滑动窗口口,不足k个不需要输出
//单调上升队列 队头即为最小值
if(i>=k-1) printf("%d ",a[q[hh]]);
}
cout<<endl;
hh=0,tt=-1;
for(int i=0;i<n;i++)
{
if(hh<=tt&&i-k+1>q[hh]) hh++;
while(hh<=tt&&a[q[tt]]<=a[i]) tt--;
q[++tt]=i;
//单调下降队列,队头即为最大值
if(i>=k-1) printf("%d ",a[q[hh]]);
}
cout<<endl;
}
首先用栈和队列暴力的做法模拟算法。删除不必要的元素,观察新的元素是否具有单调性。可以通过取队头的方式找最大值和最小值。以及二分的方法查找某个元素。
for (int i = 1, j = 0; i <= m; i ++ )
{
//为什么j=0。是将s[i]与p[j+1]相比较,则p应该向前错一位,j=0
/*在比较过程中,当两者不想等时就让p向后退,
直到j=0时为止 */
//j不等于0->不为初始状态
//s[i]!=p[j+1] 红色圆和绿色圆不相等
while (j && s[i] != p[j + 1]) j = ne[j];
if (s[i] == p[j + 1]) j ++ ;
//匹配成功
if (j == n)
{
printf("%d ", i - n);
//见图中的解释
j = ne[j];
}
}
图片模拟的是当p[i]!=p[j+1]时,p一直向后退的过程。
前提是在之前的比较过程中积累了最长后缀的数值。
这个过程也适合主串与模板串的比较过程。
//ne[1]=0 第一个字母失败了只能从头开始, 从2开始即可
for (int i = 2, j = 0; i <= n; i ++ )
{
while (j && p[i] != p[j + 1]) j = ne[j];
if (p[i] == p[j + 1]) j ++ ;
ne[i] = j;
}
#include
using namespace std;
const int N = 100010, M = 1000010;
int n, m;
int ne[N];
char s[M], p[N];
int main()
{
cin >> n >> p + 1 >> m >> s + 1;
for (int i = 2, j = 0; i <= n; i ++ )
{
while (j && p[i] != p[j + 1]) j = ne[j];
if (p[i] == p[j + 1]) j ++ ;
if(p[i+1]!=p[j+1]) ne[i] = j;
else ne[i]=ne[j];
}
for (int i = 1, j = 0; i <= m; i ++ )
{
while (j && s[i] != p[j + 1]) j = ne[j];
if (s[i] == p[j + 1]) j ++ ;
if (j == n)
{
//题目中下标从0开始,代码中下标从1开始
//i-n即可 不需要+1
printf("%d ", i - n);
j = ne[j];
}
}
return 0;
}