- 括号画家
括号匹配 stack 存下表 直接减就好
#include <iostream>
#include <cstring>
#include <map>
#include <stack>
using namespace std;
const string cd = "*(){}[]";
map<char, int> id;
int main (){
id['('] = 2;
id['{'] = 4;
id['['] = 6;
string s;
cin >> s;
stack<int> stc;
int ans = 0;
for(int i = 0; i< s.size(); i ++ ) {
if(!stc.empty() && cd[id[s[stc.top()]]] == s[i])
stc.pop();
else
stc.push(i);
if(!stc.empty())
ans = max(ans, i - stc.top());
else
ans = max(ans, i + 1);
}
cout << ans << endl;
return 0;
}
- 表达式计算
不知道为什么这题要出现多余括号。。。。orz
#include <iostream>
#include <stack>
using namespace std;
stack<int> nums;
stack<char> ops;
void cal() {
int a = nums.top(); nums.pop();
int b = nums.top(); nums.pop();
char c = ops.top(); ops.pop();
int d;
if (c == '+') d = b + a;
else if (c == '-') d = b - a;
else if (c == '*') d = b * a;
else if (c == '/') d = b / a;
else {
d = 1;
while(a --) {
d *= b;
}
}
nums.push(d);
}
int main() {
string str;
cin >> str;
string left(str.size(), '(');
str = left + str + ')';
for (int i = 0; i < str.size(); i ++ ) {
if (str[i] >= '0' && str[i] <= '9') {
int j = i, t = 0;
while (str[j] >= '0' && str[j] <= '9') {
t = t * 10 + str[j] - '0';
j ++ ;
}
nums.push(t);
i = j - 1;
} else {
char c = str[i];
if (c == '(') ops.push(c);
else if (c == '+' || c == '-') {
if (c == '-' && !(str[i - 1] >= '0' && str[i - 1] <= '9' || str[i - 1] == ')')) {
int j = i + 1, t = 0;
while (str[j] >= '0' && str[j] <= '9') {
t = t * 10 + str[j] - '0';
j ++ ;
}
nums.push(-t);
i = j - 1;
} else {
while (ops.top() != '(') cal();
ops.push(c);
}
} else if (c == '*' || c == '/') {
while (ops.top() == '*' || ops.top() == '/' || ops.top() == '^') cal();
ops.push(c);
} else if (c == '^') {
while (ops.top() == '^') cal();
ops.push(c);
} else if (c == ')') {
while (ops.top() != '(') cal();
ops.pop();
}
}
}
cout << nums.top() << endl;
return 0;
}
城市游戏 这题NOI出过 叫什么 玉蟾宫
单调栈。。。。。 其实还能用悬线法处理
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000 + 5;
int n, m;
int h[maxn][maxn];
int q[maxn], l[maxn], r[maxn];
int sol(int l[], int a[]){
a[0] = -1;
int t = 0;
for(int i = 1; i <= m; i ++ ) {
while(a[q[t]] >= a[i]) t --;
l[i] = q[t] + 1;
q[ ++ t ] = i;
}
}
int work(int a[]){
sol(l, a);
reverse(a + 1, a + 1 + m);
sol(r, a);
reverse(a + 1, a + 1 + m);
int res = 0;
for(int i = 1; i <= m; i ++ ) {
int le = l[i];
int ri = m + 1 - r[m - i + 1];
res = max(res, a[i] * (ri - le + 1));
}
return res;
}
char mp[maxn][maxn];
int main(){
cin >> n >> m;
int ans = 0;
for(int i = 1; i <= n; i ++ ) {
for(int j = 1; j <=m; j ++ ) {
cin >> mp[i][j];
if(mp[i][j] == 'F') h[i][j] = h[i - 1][j] + 1;
else continue;
}
ans = max(ans, work(h[i]));
}
cout << ans * 3 << endl;
return 0;
}
P1169 [ZJOI2007]棋盘制作 2题一样 悬线法
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e3+10;
const int INF= 0x3f3f3f3f;
const int mod = 1000000007;
int n,m,k,ans;
int a[maxn];
int l[maxn][maxn],r[maxn][maxn],up[maxn][maxn];
int mp[maxn][maxn];
int main() {
cin>>n>>m;
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
cin>>mp[i][j];
l[i][j]=r[i][j]=j;
up[i][j]=1;
}
}
for(int i=1; i<=n; i++) for(int j=2; j<=m; j++)
if(mp[i][j-1]^mp[i][j]) l[i][j]=l[i][j-1];
for(int i=1; i<=n; i++) for(int j=m-1; j>=1; j--)
if(mp[i][j]^mp[i][j+1]) r[i][j]=r[i][j+1];
int ans1=0,ans2=0;
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
if( i>1 && mp[i-1][j]^mp[i][j]) {
l[i][j]=max(l[i-1][j],l[i][j]);
r[i][j]=min(r[i-1][j],r[i][j]);
up[i][j]=up[i-1][j]+1;
}
int len=r[i][j]-l[i][j]+1;
int h=min(up[i][j],len);
ans1=max(h*h,ans1);
ans2=max(len*up[i][j],ans2);
}
}
cout<<ans1<<endl<<ans2<<endl;
return 0;
}
双栈排序 待续
滑动窗口
单调队列 保证有序
#include <iostream>
using namespace std;
const int N = 1E6+5;
int que[N], a[N];
int n, k;
void getmin(){
int h = 1, t = 0;
for(int i = 1; i <= n; i ++) {
if(h <= t && que[h] + k <= i) h ++;
while(h <= t && a[que[t]] >= a[i]) t --;
que[++ t] = i;
if(i >= k) cout << a[que[h]] << " ";
}
cout << endl;
}
void getmax(){
int h = 1, t = 0;
for(int i = 1; i <= n; i ++) {
if(h <= t && que[h] + k <= i) h ++;
while(h <= t && a[que[t]] <= a[i]) t --;
que[++ t] = i;
if(i >= k) cout << a[que[h]] << " ";
}
cout << endl;
}
int main() {
cin >> n >> k;
for(int i = 1; i <= n; i ++ ) cin >> a[i];
getmin();
getmax();
return 0;
}
内存分配 模拟题 待续
矩阵
二维hash
把这矩阵 变成 一维的算hash值 然后 都存起来。。。 算询问hash直接set查
#include <iostream>
#include <unordered_set>
using namespace std;
typedef unsigned long long ULL;
const int maxn = 1005;
ULL h[maxn][maxn], p[maxn * maxn];
int n, m, a, b;
ULL reh(ULL h[], int l, int r){
return h[r] - h[l - 1] * p[r - l + 1];
}
int main() {
cin >> n >> m >> a >> b;
string str;
p[0] = 1;
for(int i = 1; i < maxn * maxn; i ++) p[i] = 131*p[i - 1];
for(int i = 1; i <= n; i++ ){
cin >> str;
for(int j = 1; j <= m; j++ ){
h[i][j] = h[i][j - 1] * 131 + str[j - 1] - 48;
}
}
unordered_set<ULL> S;
for(int i = b; i <= m; i++){
ULL s = 0;
int l = i - b + 1, r = i;
for(int j = 1; j <= n; j ++ ){
s = s * p[b] + reh(h[j], l, r);
if(j >= a) {
s -= reh(h[j - a], l, r) * p[a * b];
S.insert(s);
}
}
}
int q;
cin >> q;
while( q -- ){
ULL s = 0;
for (int i = 1; i <= a; i ++ ){
cin >> str;
for(int j = 1; j <= b; j ++ ) {
s = s * 131 + str[j - 1] - 48;
}
}
if(S.count(s)) cout << 1 << endl;
else cout << 0 << endl;
}
return 0;
}
树形地铁系统 树的最小表达
每一次 都补充0 末位补长1 使他们格式对齐
dfs遍历树结构 str
sort 就可以按字典排序 直接找最小表达
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
string dfs(string &s, int &u){
vector<string> vc;
u ++;
while(s[u] == '0')
vc.push_back(dfs(s, u));
u ++;
sort(vc.begin(), vc.end());
string res = "0";
for(int i = 0; i < vc.size(); i ++ ) {
res += vc[i];
}
res += "1";
return res;
}
signed main() {
int n, m;
cin >> n;
while(n --) {
string s1, s2;
cin >> s1 >> s2;
s1 = '0' + s1 + '1';
s2 = '0' + s2 + '1';
int ua = 0, ub = 0;
if(dfs(s1, ua) == dfs(s2, ub))
cout << "same" << endl;
else
cout << "different" << endl;
}
return 0;
}
项链
string最小表达
#include <iostream>
#include <string>
using namespace std;
string str_mins(string s){
int n = s.size();
for(int i = 0; i < n; i ++) s.push_back(s[i]);
int i = 0, j = 1, k;
while( i < n && j < n){
for(k = 0; k < n && s[i + k] == s[j + k]; k ++ );
if(k == n) break;
if(s[i + k] > s[j + k]) {
i = i + k + 1;
if(i == j) i ++;
}else{
j = j + k + 1;
if(i == j) j ++;
}
}
string res;
k = min(i, j);
for(int i = k; i < n + k; i ++) res += s[i];
return res;
}
int main(){
string s1, s2;
cin >> s1 >> s2;
s1 = str_mins(s1);
s2 = str_mins(s2);
if(s1 == s2) {
cout << "Yes" << endl;
cout << s1 << endl;
}
else cout << "No" << endl;
return 0;
}
奶牛矩阵 二维KMP 不会 待续
匹配统计
二分hash 直接查
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int maxn = 2e5 + 5;
char s1[maxn], s2[maxn];
int ans[maxn], p[maxn], h1[maxn], h2[maxn];
bool chk(int mid, int i) {
ULL ss2 = h2[mid];
ULL ss1 = h1[i + mid - 1] - h1[i - 1] * p[mid];
if(ss2 != ss1) return 0;
else return 1;
}
int main() {
int n, m, q;
cin >> n >> m >> q;
cin >> (s1 + 1) >> (s2 + 1) ;
p[0] = 1;
for(int i = 1 ; i <= n; i ++) {
h1[i] = h1[i - 1] * 131 + s1[i];
p[i] = p[i - 1] * 131;
}
for(int i = 1 ; i <= m; i ++) {
h2[i] = h2[i - 1] * 131 + s2[i];
p[i] = p[i - 1] * 131;
}
for(int i = 1; i <= n; i ++) {
int l = 0, r = min(n, m);
while(l < r){
int mid = l + r + 1 >> 1;
if(chk(mid, i)) l = mid;
else r = mid - 1;
}
ans[l] ++ ;
}
while(q--) {
cin >> m;
cout << ans[m] << endl;
}
return 0;
}
电话列表
orz 这题我强行拍了个序。。。。。。
其实不排也行 再ins的时候 判重只需要判断 这个字符串是不是重了其他之前末位 同时它是新建立的 就是重复前醉
bool ins(string &s){
int p = 0;
bool has_new = false;
bool has_found = false;
for (int i = 0; str[i]; i ++ ){
int u = str[i] - '0';
if (!son[p][u]){
trie[p][u] = ++ idx;
has_new = true;
}
p = son[p][u];
if (eds[p]) has_found = true;
}
eds[p] = true;
return has_new && !has_found;
}
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1e5 + 5;
int trie[maxn << 1][12], tot = 1;
int eds[maxn << 1];
bool cmp(const string &a, const string &b){
return a.size() < b.size() || ( a.size() == b.size() && a < b );
}
void ins(string s){
int p = 1, len = s.size();
for(int k = 0; k < len; k ++ ) {
int ch = s[k] - '0';
if(trie[p][ch] == 0) trie[p][ch] = ++ tot;
p = trie[p][ch];
}
eds[p]++;
}
int ask(string s){
int p = 1, len = s.size();
for(int k = 0; k < len; k ++ ) {
p = trie[p][s[k] - '0'];
if(eds[p]) return 1;
if(p == 0) return 0;
}
return 0;
}
vector<string> vc;
int main(){
int cas;
cin >> cas;
while(cas -- ) {
int n;
memset(eds, 0, sizeof eds);
memset(trie, 0, sizeof trie);
vc.clear();
tot = 1;
cin >> n;
string s;
while(n -- ){
cin >> s;
vc.push_back(s);
}
int f = 1;
sort(vc.begin(), vc.end(), cmp);
for(auto i : vc){
//cout << "|" << i << endl;
if(ask(i)) {
cout << "NO" << endl;
f = 0;
break;
}
ins(i);
}
if(f) cout << "YES" << endl;
}
return 0;
}
黑盒子
对顶堆 大根堆 放小的 小根堆 放大的
大根堆 > k 往小根堆放 大根堆pop
这样小根堆就是 k + 1 小
#include <bits/stdc++.h>
using namespace std;
priority_queue<int, vector<int>, greater<int> > minheap;
priority_queue<int, vector<int>, less<int> > maxheap;
const int maxn = 3e4 + 5;
int a[maxn];
int vis[maxn];
int k, n, m;
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
}
for(int i = 1, a; i <= m ; i++ ) {
cin >> a;
vis[a]++;
}
for(int i = 1; i <= n; i ++) {
maxheap.push(a[i]);
if(maxheap.size() > k) {
minheap.push(maxheap.top());
maxheap.pop();
}
while(vis[i]) {
cout << minheap.top() << endl;
k ++ ;
maxheap.push(minheap.top());
minheap.pop();
vis[i]--;
}
}
return 0;
}
生日礼物
没有写出 待续