L2-004 这是二叉搜索树吗? (25 分)
口胡 搜索树
中序遍历是有序的 树 左边小于右边 所以在前序遍历里一旦找到第一个比当前比较用的跟大的 便是右子树的开端
这题 输入可能是镜像树的前序 所以 改下一开始建立树函数大小于号就好
当 是镜像树时 显然 不能正常建立 所以后续遍历数组不会到达n个

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn= 1e3+5;

int a[maxn];
int b[maxn];
int cnt,n;

void getrt1(int l,int r){
	if(l>r) return ;
	int i = l + 1 , j = r ;
	while(i<=r&&a[l]>a[i]) i++;
	while(j>l&&a[l]<=a[j]) j--;
	if(i-j!=1) return ;
	getrt1(l+1,j);
	getrt1(i,r);
	b[++cnt]=a[l];
} 

void getrt2(int l,int r){
	if(l>r) return ;
	int i = l + 1 , j = r ;
	while(i<=r&&a[l]<=a[i]) i++;
	while(j>l&&a[l]>a[j]) j--;
	if(i-j!=1) return ;
	getrt2(l+1,j);
	getrt2(i,r);
	b[++cnt]=a[l];
} 

int main() {
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	getrt1(1,n);
	if(cnt!=n){
		cnt=0;
		getrt2(1,n);
	}
	if(cnt!=n){
		cout<<"NO\n";
	}else{
		cout<<"YES\n"<<b[1];
		for(int i=2;i<=n;i++){
			cout<<" "<<b[i];
		}puts("");
	}
	return 0;
}

L2-006 树的遍历 (25 分)
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列
层序遍历 只好先建树了
按找前序遍历的方法建树。。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 35;
int n, in_order[maxn], post_order[maxn];
vector<int> ans;

struct Node {
	int v;
	int left, right;
} tree[maxn];

int Root;
int bulid(int L1, int R1, int L2, int R2) {
	if (L1 > R1) return -1;
	int root = post_order[R2];
	int p = L1;
	while (in_order[p] != root) p++;
	int cnt = p - L1;
	tree[root].left = bulid(L1, p - 1, L2, L2 + cnt - 1);
	tree[root].right = bulid(p + 1, R1, L2 + cnt, R2 - 1);
	return root;
}

void bfs() {
	queue<int> Q;
	Q.push(Root);
	while (!Q.empty()) {
		int u = Q.front();
		Q.pop();
		ans.push_back(u);
		if (tree[u].left != -1) Q.push(tree[u].left);
		if (tree[u].right != -1) Q.push(tree[u].right);
	}
}

int main() {
	scanf("%d", &n);
	for (int i = 1; i <=n; i++) scanf("%d", &post_order[i]);
	for (int i = 1; i <=n; i++) scanf("%d", &in_order[i]);
	Root = bulid(1, n , 1, n );
	bfs();
	for (int i = 0; i < ans.size(); i++) {
		if (i != 0) printf(" ");
		printf("%d", ans[i]);
	}
	printf("\n");
	return 0;
}

https://vjudge.net/problem/HRBUST-2040
二叉树的遍历 HRBUST - 2040
给出一棵二叉树的中序和前序遍历,输出它的后序遍历。
每组数据的第一行包括一个整数n,表示这棵二叉树一共有n个节点。
接下来的一行每行包括n个整数,表示这棵树的中序遍历。
接下来的一行每行包括n个整数,表示这棵树的前序遍历。

#include<cstdio>
#include<iostream>
using namespace std;
const int maxn= 1e3+5;

int n;
int a[maxn],b[maxn],c[maxn];
int f=0;
void fun(int p1, int p2, int q1, int q2){
// cout<<p1<<" "<<p2<<" | "<<q1<<" "<<q2<<endl;
	if(p1>p2 || q1>q2) return;
	int i = 0;
	while(a[p1] != b[i+q1]) i++;
// cout<<i<<endl;
	fun(p1+1,p1+i,q1,q1+i-1);
	fun(p1+i+1,p2,q1+i+1,q2);
// if(f) cout<<" ";
// f=1;
	cout<<a[p1]<<" ";
}
int main() {
while(cin>>n){
	f=0;
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=1;i<=n;i++) cin>>a[i];
	fun(1,n,1,n);
	cout<<endl;
}
	return 0;
}

L2-011 玩转二叉树 (25 分)
给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。
几乎同上

#include<bits/stdc++.h>
using namespace std;
const int maxn = 35;
int n, pre_order[maxn], in_order[maxn];
vector<int> ans;

struct Node {
	int left, right;
} tree[maxn];

int Root;
int bulid(int L1, int R1, int L2, int R2) {
	if (L2 > R2) return -1;
	int root = pre_order[L1];
	int p = L2; 
	while (in_order[p] != root) p++;
	int cnt = p - L2;
	tree[root].left = bulid(L1+1, L1+cnt, L2,p-1);
	tree[root].right = bulid(L1+cnt+1, R1,p+1, R2 );
	return root;
}

void bfs() {
	queue<int> Q;
	Q.push(Root);
	while (!Q.empty()) {
		int u = Q.front();
		Q.pop();
		ans.push_back(u);
		if (tree[u].right != -1) Q.push(tree[u].right);
		if (tree[u].left != -1) Q.push(tree[u].left);
	}
}

int main() {
	scanf("%d", &n);
	for (int i = 1; i <=n; i++) scanf("%d", &in_order[i]);
	for (int i = 1; i <=n; i++) scanf("%d", &pre_order[i]);
	Root = bulid(1, n , 1, n );
	bfs();
// cout<<Root<<endl;
	for (int i = 0; i < ans.size(); i++) {
		if (i != 0) printf(" ");
		printf("%d", ans[i]);
	}
	printf("\n");
	return 0;
}

L2-012 关于堆的判断

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1005<<1;
int n,m,x,y;
vector<int> ans;
int a[maxn];
int rt=0;
map<int,int> b;
string tmp;
void insert(int x){
	a[++rt]=x;
	int t=rt;
	while(t>1&&a[t/2]>a[t]){ // > 1 
		swap(a[t/2],a[t]);
		t/=2;
	}
	a[t]=x;
}

int main() {
	cin>>n>>m;
	for(int i=0;i<n;i++) {
		cin>>x;
		insert(x);
	}
	for(int i=1;i<=n;i++){
		b[a[i]]=i;
	}
	for(int i=0;i<m;i++){
		cin>>x;
		cin>>tmp;
		if(tmp[0]=='i'){
			cin>>tmp;
			if(tmp[0]=='t'){
				cin>>tmp;
				if(tmp[0]=='r'){
					if(b[x]==1){
						cout<<'T'<<endl;
					}else cout<<"F"<<endl;
				}else{
					cin>>tmp;
					cin>>y;
					if(b[x]==b[y]/2){
						cout<<"T\n";
					}else cout<<"F\n";
				}
			}else{
				cin>>tmp>>tmp>>y;
				if(b[x]/2==b[y]){
					cout<<"T"<<endl;
				}else cout<<"F"<<endl;
			}
		}else{
			cin>>y>>tmp>>tmp;
			if(b[x]/2==b[y]/2){
				cout<<"T"<<endl;
			}else cout<<"F\n";
		}
	}
	return 0;
}

L3-002 特殊堆栈 (30 分)
想不到吧 神tmd线段树 orz
被人提示了一下 很快A了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int MN = 1e5;
int n,m,cmd,st,ed,k,rt;
stack<int> s;
int tr[maxn<<2];

void my_push(int l,int r, int p,int rt,int t){
	//cout<<l<<" "<<r<<" "<<p<<" "<<rt<<" "<<t<<endl;
	if(l==r){
		tr[rt]+=t;
		return;
	}else{
		int mid=(l+r)>>1;
		if(p<=mid) my_push(l,mid,p,rt<<1,t);
		else my_push(mid+1,r,p,rt<<1|1,t);
	}
	tr[rt]=tr[rt<<1]+tr[rt<<1|1];
}

int dfs(int x,int rt,int l,int r){
// cout<<x<<" "<<rt<<" "<<l<<" "<<r<<endl;
	if(l==r) return l;
	if(tr[rt<<1]>=x) {
		return dfs(x,rt<<1,l,(l+r)>>1);
	}
	else{
		x-=tr[rt<<1];
		return dfs(x,rt<<1|1,((l+r)>>1)+1,r);
	} 
}

void my_peek(){
	if(s.empty()){
		cout<<"Invalid\n";
		return ; 
	}
	int cnt=(tr[1]+1)>>1;
	cout<<dfs(cnt,1,1,MN)<<endl;
}

void my_pop(){
	if(s.empty()) cout<<"Invalid\n";
	else{
		cout<<s.top()<<endl;
		my_push(1,MN,s.top(),1,-1);
		s.pop();
	}
}

void slove(){
	cin>>n;
	string str;
	for(int i=0;i<n;i++){
		cin>>str;
		if(str.size()==3){
			my_pop();
		}else if(str.size()==4){
			cin>>m;
			s.push(m);
			my_push(1,MN,m,1,1);
		}else{
			my_peek();
		}
	}
}

int main() {
	slove();
	return 0;
}

L2-013 红色警报 (25 分)
战争中保持各个城市间的连通性非常重要。本题要求你编写一个报警程序,当失去一个城市导致国家被分裂为多个无法连通的区域时,就发出红色警报。注意:若该国本来就不完全连通,是分裂的k个区域,而失去一个城市并不改变其他城市之间的连通性,则不要发出警报。
并查集跑联通度
为什么 上一次的联通度 CNT ==这次tmp+1 || tmp 是不改变连通性的
破坏了联通度 会割裂一个 联通子图 肯定+2了
有些联通度不变 是因为 本来我割裂的就是一个孤立点
tmp加一是:
仅攻占一个城市 却没有割裂其他城市对 除该城市联系外 的 关系

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;

const int maxn = 5005;

bool v[maxn];
pair<int,int> a[maxn];

int pre[maxn];

void init(int n) {
	for(int i=0; i<=n; i++) pre[i]=i;
}
int finds(int x) {
	return pre[x]!=x?pre[x]=finds(pre[x]):x;
}
void unions(int x,int y) {
	x=finds(x);
	y=finds(y);
	x!=y?pre[x]=y:1;
}

int main() {
	int n,m,k,x;
	cin>>n>>m;
	init(n);
	for(int i=1; i<=m; i++) {
		cin>>a[i].first>>a[i].second;
		unions(a[i].first,a[i].second);
	}
	int cnt=0,tmp=0;
	for(int i=0; i<n; i++) {
		if(pre[i]==i) cnt++;
	}
	cin>>k;
	int ks=0;
	while(ks++!=k) {
		cin>>x;	
		v[x]=1;
		init(n);	
		tmp=0;
		for(int i=1; i<=m; i++) {
			if(v[a[i].first]||v[a[i].second]) continue;
			else unions(a[i].second,a[i].first);
		}
		for(int i=0; i<n; i++) {
			if(pre[i]==i) tmp++;
		}
		if(tmp<=cnt+1) {/////////////////
			printf("City %d is lost.\n",x);
		} else {
			printf("Red Alert: City %d is lost!\n",x);
		}
		cnt=tmp;
	}
	if(n==k) cout<<"Game Over.\n";
	return 0;
}