title: NEU_Train_Camp_2020_基础数据结构
date: 2020-07-13 21:13:03
tags:
- c++
categories: - New
cover:
基础数据结构
A - Web Navigation
POJ-1028
#include <string>
#include <iostream>
#include <stack>
using namespace std;
void clear(stack<string> &a)
{
while (!a.empty())
a.pop();
}
int main(void)
{
stack<string> forw, bac;
string cur = "http://www.acm.org/";
string oper;
while (cin >> oper and oper != "QUIT")
{
if (oper == "VISIT")
{
clear(forw);
bac.push(cur);
cin >> cur;
cout << cur << endl;
}
else if (oper == "BACK")
{
if (bac.empty())
cout << "Ignored" << endl;
else
{
forw.push(cur);
cur = bac.top();
bac.pop();
cout << cur << endl;
}
}
else
{
//FORWARD
if (forw.empty())
cout << "Ignored" << endl;
else
{
bac.push(cur);
cur = forw.top();
forw.pop();
cout << cur << endl;
}
}
}
return 0;
}
B - 简单计算器
HDU 1237
我吐了我吐了我吐了,wa了一上午,我吐了我吐了我吐了
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
stack<double> num;
string in;
while (getline(cin, in))
{
char op = '!';
if (in.size() == 1 && in[0] == '0')
break;
for (size_t i = 0; i < in.size(); i++)
{
if (in[i] == ' ')
continue;
if (isdigit(in[i]))
{
double n = in[i] - '0';
for (size_t j = i + 1; j < in.size(); j++)
{
if (isdigit(in[j]))
{
n = n * 10 + in[j] - '0';
i = j + 1;
}
else
break;
}
if (op == '!')
num.push(n * 1.0);
else
{
double t;
switch (op)
{
case '+':
num.push(n);
break;
case '-':
num.push(-n);
break;
case '*':
t = num.top();
num.pop();
num.push(t * n);
break;
case '/':
t = num.top();
num.pop();
num.push(t / n);
break;
default:
break;
}
op = '!';
}
}
else
{
op = in[i];
}
}
double ans = 0;
while (!num.empty())
{
ans += num.top();
num.pop();
}
// cout << fixed << setprecision(2) << ans << endl; //G++交上去wa , C++ 交上去ac ,vjudge平台
printf("%.2lf
", ans);
}
return 0;
}
C - Catch That Cow
POJ 3278
直接bfs,这简单题应该放在第一场第一题(逃)
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
int n, k;
bool vis[100002];
bool isLegal(pair<int, int> t)
{
if (0 <= t.first and t.first <= 100000 and !vis[t.first])
return true;
return false;
}
int bfs(int s)
{
queue<pair<int, int> > que;
que.push(make_pair(s, 0));
vis[s] = true;
while (!que.empty())
{
pair<int, int> f = que.front();
que.pop();
if (f.first == k)
{
return f.second;
}
pair<int, int> t = f;
--t.first;
if (isLegal(t))
{
vis[t.first] = true;
t.second++;
que.push(t);
}
t = f;
t.first++;
if (isLegal(t))
{
vis[t.first] = true;
t.second++;
que.push(t);
}
t = f;
t.first *= 2;
if (isLegal(t))
{
vis[t.first] = true;
t.second++;
que.push(t);
}
}
return -1;
}
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
cin >> n >> k;
cout << bfs(n) << endl;
return 0;
}
D - Team Queue
HDU 1387 && UVa 540
使用map
对队伍进行分组,一个队伍对应一个value ... 当然unordered_map
更快,奈何hdu,poj都不支持
常数时间的插入删除,使用std::list<int>
模拟队列
vector<list<int>::iterator>
存每个队伍,在队列中最后一个成员的位置.
pop
元素是该队伍在队列中的唯一一个元素,要更新该队伍的迭代器为end()
之前我这里没有注意,re了
注意:list
进行pop
后,指向的迭代器会失效 , 所以re了,而不是wa了
#include <cstdio>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#include <map>
#include <list>
using namespace std;
int main(void)
{
list<int> que;
map<int, int> vis;
vector<list<int>::iterator> pos;
int count = 1;
int t;
while (scanf("%d", &t))
{
if (t == 0)
break;
que.clear();
vis.clear();
pos.clear();
pos.resize(t);
fill(pos.begin(), pos.end(), que.end());
printf("Scenario #%d
", count++);
for (size_t i = 0; i < t; i++)
{
int n;
scanf("%d", &n);
for (int j = 0; j < n; j++)
{
int in;
scanf("%d", &in);
vis[in] = i + 1;
}
}
char op[100];
while (scanf("%s", op) and op[0] != 'S')
{
if (op[0] == 'D')
{
printf("%d
", que.front());
if (pos[vis[que.front()] - 1] == que.begin()) //这里re了
pos[vis[que.front()] - 1] = que.end();
que.pop_front();
}
else
{
int in;
scanf("%d", &in);
int temp = vis[in] - 1;
list<int>::iterator nowp = pos[temp];
if (nowp == que.end())
pos[temp] = que.insert(nowp, in);
else
pos[temp] = que.insert(++nowp, in);
}
}
printf("
");
}
return 0;
}
不完全总结迭代器失效
- 序列式容器
- 内存重新分配时 , 所有的迭代器都将失效
- 删除当前的iterator会使后面所有元素的iterator都失效
insert()
erase()
- 关联式容器
- 被删除的元素的迭代器失效
E - Bad Hair Day
POJ 3250
单调栈
最开始两层循环暴力,tle
看了题解使用了单调栈
我原来想的是每头牛最多能看见他右边几头牛 , 单调栈代表的思想是每头牛能被他左边最多几头牛看见,一头牛入栈时,栈内元素数量就是能看见他的牛的数量.
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n;
cin >> n;
long long ans(0);
stack<int> s;
int h;
cin >> h;
s.push(h);
for (int i = 1; i < n; i++)
{
cin >> h;
while (!s.empty() and s.top() <= h)
{
s.pop();
}
ans += s.size();
s.push(h);
}
cout << ans;
return 0;
}
与上面奶牛那个不太一样
class Solution
{
public:
int largestRectangleArea(vector<int> &heights)
{
vector<pair<int, int>> touch(heights.size());
stack<int> s;
for (size_t i = 0; i < heights.size(); i++)
{
//入栈时确定左边界,出栈确定右边界
while (!s.empty() and heights[i] <= heights[s.top()])
{
touch[s.top()].second = i - 1;
s.pop();
}
touch[i].first = s.empty() ? 0 : s.top() + 1;
s.push(i);
}
while (!s.empty())
{
touch[s.top()].second = heights.size() - 1;
s.pop();
}
int tmax = 0;
for (size_t i = 0; i < touch.size(); i++)
{
tmax = max(tmax, (touch[i].second - touch[i].first + 1) * heights[i]);
}
return tmax;
}
//另一种写法,不够优雅
int largestRectangleArea1(vector<int> &heights)
{
vector<pair<int, int>> res(heights.size());
stack<int> s;
for (int i = 0; i < heights.size(); i++)
{
while (!s.empty() and heights[i] <= heights[s.top()])
s.pop();
res[i].first = s.empty() ? -1 : s.top();
s.push(i);
}
while (!s.empty())
{
s.pop();
}
for (int i = heights.size() - 1; i >= 0; i--)
{
while (!s.empty() and heights[i] <= heights[s.top()])
s.pop();
res[i].second = s.empty() ? heights.size() : s.top();
s.push(i);
}
int tmax = 0;
for (int i = 0; i < res.size(); i++)
{
if ((res[i].second - res[i].first - 2 + 1) * heights[i] > tmax)
tmax = (res[i].second - res[i].first - 2 + 1) * heights[i];
}
return tmax;
}
};
F - How Many Tables
简单的并查集
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
int n, m;
int fa[1010];
int findfa(int a)
{
if (fa[a] == a)
{
return a;
}
else
{
return fa[a] = findfa(fa[a]);
}
}
void unio(int a, int b)
{
a = findfa(a);
b = findfa(b);
if (a != b)
fa[b] = a;
}
void init()
{
for (size_t i = 1; i <= n; i++)
{
fa[i] = i;
}
}
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
cin >> t;
while (t--)
{
cin >> n >> m;
init();
for (int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
unio(a, b);
}
int ans(0);
for (int i = 1; i <= n; i++)
{
if (i == fa[i])
ans++;
}
cout << ans
<< endl;
}
return 0;
}
G - 畅通工程
HDU 1863
没思路.
最小生成树, 挑战程序设计竞赛 p105
prim+邻接表+优先队列 _没太理解
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#define mp(a, b) make_pair(a, b)
using namespace std;
using p = pair<int, int>;
vector<p> edge[102];
bool vis[102];
int n, m;
void prim()
{
priority_queue<p, vector<p>, greater<p>> que;
que.push(mp(0, 1));
int ans = 0;
while (!que.empty())
{
p u = que.top();
que.pop();
if (!vis[u.second])
{
vis[u.second] = true;
ans += u.first;
for (int i = 0; i < edge[u.second].size(); i++)
{
p v = edge[u.second][i];
if (!vis[v.second])
{
que.push(v);
}
}
}
}
//binary_search要求数组有序,故使用find
if (find(vis + 1, vis + m + 1, false) == vis + m + 1)
cout << ans << endl;
else
cout << '?' << endl;
}
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
while (cin >> n >> m and n != 0)
{
for (size_t i = 0; i <= m; i++)
{
edge[i].clear();
}
memset(vis, 0, sizeof(vis));
for (size_t i = 0; i < n; i++)
{
int a, b, c;
cin >> a >> b >> c;
edge[a].push_back(mp(c, b));
edge[b].push_back(mp(c, a));
}
prim();
}
return 0;
}
网上抄的
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <stack>
#include <queue>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 120
typedef long long ll;
int n, q;
int V;
int res;
int mincost[MAXN];
int used[MAXN];
struct edge
{
int to, cost;
edge() {}
edge(int to, int cost) : to(to), cost(cost) {}
};
vector<edge> G[MAXN]; //存放从i出发的边
typedef pair<int, int> P; //first存放距离,second存放节点
priority_queue<P, vector<P>, greater<P>> que;
void prim()
{
memset(used, 0, sizeof(used));
fill(mincost, mincost + V, INF);
res = 0;
que.push(P(0, 0));
while (!que.empty())
{
P p = que.top();
que.pop();
int v = p.second, d = p.first;
if (used[v])
continue;
used[v] = 1;
res += d;
for (int i = 0; i < G[v].size(); i += 1)
{
edge e = G[v][i];
if ((mincost[e.to] > e.cost) && !used[i])
{
mincost[e.to] = e.cost;
que.push(P(mincost[e.to], e.to));
}
}
}
printf("%d
", res);
}
int main()
{
while (scanf("%d", &n) != EOF)
{
memset(G, 0, sizeof(G)); //每次要初始化啊
for (int i = 0; i < n; i += 1)
{
for (int j = 0; j < n; j += 1)
{
int a;
cin >> a;
G[i].push_back(edge(j, a));
}
}
cin >> q;
for (int i = 0; i < q; i += 1)
{
int a, b;
cin >> a >> b;
G[a - 1][b - 1].cost = G[b - 1][a - 1].cost = 0;
}
V = n;
prim();
}
return 0;
}
H - 食物链
POJ - 1182
我称之为并查集的进阶
挑战程序设计竞赛 p88
这种比带权那种解法更容易理解,但显著的缺点就是废空间;
使用cin
会tle
#include <cstdio>
#include <iostream>
using namespace std;
int n, k;
int fa[150014];
void init()
{
for (int i = 1; i <= 3 * n; i++)
{
fa[i] = i;
}
}
int findfa(int a)
{
if (fa[a] == a)
return a;
else
return fa[a] = findfa(fa[a]);
}
void unio(int a, int b)
{
a = findfa(a);
b = findfa(b);
if (a != b)
fa[a] = b;
}
bool judge(int a, int b)
{
return findfa(a) == findfa(b);
}
int main(void)
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
// cin >> n >> k;
scanf("%d %d", &n, &k);
int ans = 0;
init();
while (k--)
{
int d, x, y;
scanf("%d %d %d", &d, &x, &y);
// cin >> d >> x >> y; // tle
if (x > n || y > n || (d == 2 && x == y))
ans++;
else
{
//若D=1,则表示X和Y是同类。
if (d == 1)
{
if (judge(x, y + n) || judge(y, x + n)) //判断是否为同类,不是直接去判断,而是没有吃与被吃的关系就是同类
ans++;
else
{
unio(x, y);
unio(x + n, y + n);
unio(x + 2 * n, y + 2 * n);
}
}
else
{ //若D=2,则表示X吃Y。
if (judge(x, y) || judge(y, x + n)) //x,y是同类 或者y吃x
ans++;
else
{
unio(x, y + n);
unio(x + n, y + 2 * n);
unio(x + 2 * n, y);
}
}
}
}
printf("%d
", ans);
// cout << ans << endl;
return 0;
}
带权并查集
https://blog.csdn.net/Cfreezhan/article/details/8767413
https://zhuanlan.zhihu.com/p/104581351
我???
#include <cstdio>
const int MAX = 50005;
int parent[MAX];
int rank[MAX];
void MakeSet(int x)
{
parent[x] = x;
rank[x] = 0;
}
//查找x的集合,回溯时压缩路径,并修改x与father[x]的关系
int FindSet(int x)
{
if (x == parent[x])
return x;
else
{
//rank[x] = (rank[x] + rank[parent[x]]) % 3; // !!!这么写会wa
//return parent[x] = FindSet(parent[x]); //wa
int t = parent[x];
parent[x] = FindSet(parent[x]);
rank[x] = (rank[x] + rank[t]) % 3;
return parent[x]; // 这样就ac了
}
}
//合并x,y所在的集合
void Union(int x, int y, int d)
{
int xRoot = FindSet(x);
int yRoot = FindSet(y);
//将集合x所在合并到y所在集合上
parent[xRoot] = yRoot;
//更新x的根与x的父节点的关系
rank[xRoot] = (rank[y] - rank[x] + 3 + d) % 3;
}
int main()
{
int ans = 0;
int n, k, x, y, d, xRoot, yRoot;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; ++i)
MakeSet(i);
while (k--)
{
scanf("%d%d%d", &d, &x, &y);
//如果x或y比n大,或x吃x,是假话
if (x > n || y > n || (d == 2 && x == y))
{
ans++;
}
else
{
xRoot = FindSet(x);
yRoot = FindSet(y);
//如果x,f的父节点相同 ,那么可以判断给出的关系是否正确的
if (xRoot == yRoot)
{
if ((rank[x] - rank[y] + 3) % 3 != d - 1)
ans++;
}
else
{
//否则合并x,y
Union(x, y, d - 1);
}
}
}
printf("%d
", ans);
return 0;
}
I - Snowflake Snow Snowflakes
POJ 3349
使用set<vector<int> >
会tle,poj又用不了unordered_set
自建hash表
纯c , 记得用gcc提交 , 用 c 提交会 ce
事实证明,用纯c不会更快,也不会更小 (逃)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
struct node
{
int a[6];
};
struct node hash[15000][1000];
int hashLen[15000];
int getHash(struct node *p)
{
long long t = 0;
int i;
for (i = 0; i < 6; i++)
{
t += p->a[i];
}
return (int)(t % 14997);
}
int cmp(const void *a, const void *b)
{
return *(int *)(a) - *(int *)(b);
}
int isSame(struct node j, struct node k)
{
qsort(j.a, 6, sizeof(int), cmp);
qsort(k.a, 6, sizeof(int), cmp);
int i;
for (i = 0; i < 6; i++)
{
if (j.a[i] != k.a[i])
return 0;
}
return 1;
}
int hashInsert(struct node *t)
{
int tkey = getHash(t);
int i;
for (i = 0; i < hashLen[tkey]; i++)
{
if (isSame(*t, hash[tkey][i]))
{
return 0;
}
}
hash[tkey][hashLen[tkey]++] = *t;
return 1;
}
int main()
{
int t;
scanf("%d", &t);
struct node tmp;
int i;
for (i = 0; i < t; i++)
{
int j;
for (j = 0; j < 6; j++)
{
scanf("%d", &tmp.a[j]);
}
if (!hashInsert(&tmp))
{
printf("Twin snowflakes found.");
return 0;
}
}
printf("No two snowflakes are alike.
");
return 0;
}
记录下ce原因
Main.c
F: emp21837784.264775Main.c(34) : error C2143: syntax error : missing ';' before 'type'
F: emp21837784.264775Main.c(35) : error C2065: 'i' : undeclared identifier
F: emp21837784.264775Main.c(35) : error C2065: 'i' : undeclared identifier
F: emp21837784.264775Main.c(35) : error C2065: 'i' : undeclared identifier
F: emp21837784.264775Main.c(37) : error C2065: 'i' : undeclared identifier
F: emp21837784.264775Main.c(37) : error C2065: 'i' : undeclared identifier
F: emp21837784.264775Main.c(62) : error C2143: syntax error : missing ';' before 'type'
F: emp21837784.264775Main.c(63) : error C2143: syntax error : missing ';' before 'type'
F: emp21837784.264775Main.c(64) : error C2065: 'i' : undeclared identifier
F: emp21837784.264775Main.c(64) : error C2065: 'i' : undeclared identifier
F: emp21837784.264775Main.c(64) : error C2065: 'i' : undeclared identifier
F: emp21837784.264775Main.c(69) : error C2065: 'tmp' : undeclared identifier
F: emp21837784.264775Main.c(69) : error C2224: left of '.a' must have struct/union type
F: emp21837784.264775Main.c(71) : error C2065: 'tmp' : undeclared identifier
poj用的是远古的vc++
小改一下,就ac了
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
struct node
{
int a[6];
};
struct node hash[15000][1000];
int hashLen[15000];
int getHash(struct node *p)
{
long long t = 0;
int i;
for (i = 0; i < 6; i++)
{
t += p->a[i];
}
return (int)(t % 14997);
}
int cmp(const void *a, const void *b)
{
return *(int *)(a) - *(int *)(b);
}
int isSame(struct node j, struct node k)
{
int i;
qsort(j.a, 6, sizeof(int), cmp);
qsort(k.a, 6, sizeof(int), cmp);
for (i = 0; i < 6; i++)
{
if (j.a[i] != k.a[i])
return 0;
}
return 1;
}
int hashInsert(struct node *t)
{
int tkey = getHash(t);
int i;
for (i = 0; i < hashLen[tkey]; i++)
{
if (isSame(*t, hash[tkey][i]))
{
return 0;
}
}
hash[tkey][hashLen[tkey]++] = *t;
return 1;
}
int main()
{
int t;
int i;
int j;
struct node tmp;
scanf("%d", &t);
for (i = 0; i < t; i++)
{
for (j = 0; j < 6; j++)
{
scanf("%d", &tmp.a[j]);
}
if (!hashInsert(&tmp))
{
printf("Twin snowflakes found.");
return 0;
}
}
printf("No two snowflakes are alike.
");
return 0;
}
J - Power Strings
最小循环节若存在,则其长度等于len-next[len]
,证明
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
int Next[1000010];
using namespace std;
int getNext(string &a)
{
Next[0] = -1;
int i = 0, j = -1;
while (i < a.length())
{
if (j == -1 or a[i] == a[j])
Next[++i] = ++j;
else
j = Next[j];
}
return Next[a.length()];
}
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
string a;
while (cin >> a and a[0] != '.')
{
int n = a.length();
int x = n - getNext(a);
if (n % x == 0) // 若有解,那么最短循环节长度为 x = n - nex[n] 。
{
cout << n / x
<< endl;
}
else
{
cout << 1 << endl;
}
}
return 0;
}
kmp模板
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
int pnext[2000000];
using namespace std;
void getNext(string &str)
{
pnext[0] = -1;
int j = 0, k = -1;
while (j < str.length() - 1)
{
if (k == -1 or str[j] == str[k])
{
pnext[++j] = ++k;
}
else
{
k = pnext[k];
}
}
}
string kmp(string &s, string &patten)
{
int i = 0, j = 0;
while (i < s.length())
{
if (j == -1 or s[i] == patten[j])
{
++i, ++j;
}
else
{
j = pnext[j];
}
if (j == patten.length())
{
return s.substr(i - j, j);
// j = pnext[j]; //继续寻找
}
}
return "";
}
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
string s = "abbbadabaabcabadba";
string pattern = "abaabcaba";
getNext(pattern);
cout << kmp(s, pattern);
return 0;
}
K - A Simple Problem with Integers
此题删掉了
L - Sliding Window
POJ 2823
单调队列
c++ ac ,g++ wa ,太诡异了
题解的代码g++提交上去就ac
诡异,诡异 , 对数组的随机访问很耗时吗?poj g++的诡异
#include <vector>
#include <deque>
#include <cstdio>
using namespace std;
vector<int> arr;
int n, k;
void slidingMin()
{
deque<int> que;
for (int i = 0; i < k; i++)
{
while (!que.empty() && arr[que.back()] >= arr[i])
que.pop_back();
que.push_back(i);
}
printf("%d", arr[que.front()]);
for (int i = k; i < n; i++)
{
while (!que.empty() && i - que.front() >= k)
que.pop_front();
while (!que.empty() && arr[que.back()] >= arr[i])
que.pop_back();
que.push_back(i);
printf(" %d", arr[que.front()]);
}
printf("
");
}
void slidingMax()
{
deque<int> que;
for (size_t i = 0; i < k; i++)
{
while (!que.empty() && arr[que.back()] <= arr[i])
que.pop_back();
que.push_back(i);
}
printf("%d", arr[que.front()]);
for (size_t i = k; i < n; i++)
{
while (!que.empty() && i - que.front() >= k)
que.pop_front();
while (!que.empty() && arr[que.back()] <= arr[i])
que.pop_back();
que.push_back(i);
printf(" %d", arr[que.front()]);
}
}
int main(void)
{
scanf("%d %d", &n, &k);
arr.resize(n);
for (size_t i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
slidingMin();
slidingMax();
return 0;
}
M - Feel Good
前缀和+单调栈
https://blog.nowcoder.net/n/7adc5e27098442cda1e6d31677495ed1
我太**气了 , tle 我明白,scanf
and printf
比 cin
and cout
快 (c++11以上,关闭同步,应该相差不大)
wa我实在是不明白,再也不用pair
了
先放ac版
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
using namespace std;
long long in[100100];
long long sum[100100];
int l[100100], r[100100];
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
scanf("%d", &t);
sum[0] = 0;
stack<int> s;
for (int i = 1; i <= t; i++)
{
scanf("%d", &in[i]);
sum[i] = sum[i - 1] + in[i];
}
for (int i = 1; i <= t; i++)
{
while (!s.empty() && in[i] <= in[s.top()])
{
// touch[s.top()].second = i - 1;
r[s.top()] = i - 1;
s.pop();
}
l[i] = s.empty() ? 1 : s.top() + 1;
s.push(i);
}
while (!s.empty())
{
// touch[s.top()].second = t;
r[s.top()] = t;
s.pop();
}
long long tmax = 0;
int rl, rr;
for (int i = 1; i <= t; i++)
{
long long res = (in[i]) * (sum[r[i]] - sum[l[i] - 1]);
if (tmax <= res)
{
tmax = res;
rl = l[i];
rr = r[i];
}
}
printf("%lld
", tmax);
printf("%d %d
", rl, rr);
return 0;
}
tle版
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#define p pair<int, int>
using namespace std;
long long in[100100];
long long sum[100100];
p touch[100100];
int l[100100], r[100100];
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
cin >> t;
sum[0] = 0;
stack<int> s;
for (int i = 1; i <= t; i++)
{
cin >> in[i];
sum[i] = sum[i - 1] + in[i];
}
for (int i = 1; i <= t; i++)
{
while (!s.empty() && in[i] <= in[s.top()])
{
// touch[s.top()].second = i - 1;
r[s.top()] = i - 1;
s.pop();
}
l[i] = s.empty() ? 1 : s.top() + 1;
s.push(i);
}
while (!s.empty())
{
// touch[s.top()].second = t;
r[s.top()] = t;
s.pop();
}
long long tmax = 0;
int rl, rr;
for (int i = 1; i <= t; i++)
{
long long res = (in[i]) * (sum[r[i]] - sum[l[i] - 1]);
if (tmax <= res)
{
tmax = res;
rl = l[i];
rr = r[i];
}
}
printf("%lld
", tmax);
printf("%d %d
", rl, rr);
return 0;
}
wa版
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#define p pair<int, int>
using namespace std;
long long in[100100];
long long sum[100100];
int main(void)
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
cin >> t;
vector<p> touch(t + 1);
sum[0] = 0;
stack<int> s;
for (int i = 1; i <= t; i++)
{
cin >> in[i];
sum[i] = sum[i - 1] + in[i];
}
for (int i = 1; i <= t; i++)
{
while (!s.empty() && in[i] <= in[s.top()])
{
touch[s.top()].second = i - 1;
s.pop();
}
touch[i].first = s.empty() ? 1 : s.top() + 1;
s.push(i);
}
while (!s.empty())
{
touch[s.top()].second = t;
s.pop();
}
long long tmax = 0, l, r;
for (int i = 1; i <= t; i++)
{
long long res = (in[i]) * (sum[touch[i].second] - sum[touch[i].first - 1]);
if (tmax <= res)
{
tmax = res;
l = touch[i].first;
r = touch[i].second;
}
}
printf("%I64d
", tmax);
printf("%d %d
", l, r);
return 0;
}