第五周训练 | 二叉树+线段树

A - Binary Tree Traversals

记一个模板

#include<iostream>
using namespace std;
typedef struct Tree{
    Tree *left;
    Tree *right;
    int value;
}Tree;
 
Tree *root;
 
 
Tree* create(int *preorder,int *inorder,int n)
{
    Tree *temp;
    for(int i=0;i<n;i++)
    {
        if(preorder[0]==inorder[i])
        {
            temp=(Tree*)malloc(sizeof(Tree));
            temp->value=inorder[i];          
            temp->left=create(preorder+1,inorder,i);
            temp->right=create(preorder+i+1,inorder+i+1,n-i-1);
            return temp;
        }
 
    }
    return NULL;
}
 
void postOrder(Tree *postTree)
{
    if(postTree!=NULL)
    {
        postOrder(postTree->left);
        postOrder(postTree->right);
        if(postTree==root)
            printf("%d\n",postTree->value);
        else
            printf("%d ",postTree->value);
    }
}
 
int main()
{
    int n;
    int preorder[2010],inorder[2010];
    while(scanf("%d",&n)!=EOF)
    {
        root=NULL;
        for(int i=0;i<n;i++)
            scanf("%d",&preorder[i]);
        for(int i=0;i<n;i++)
            scanf("%d",&inorder[i]);
        root=create(preorder,inorder,n);
        postOrder(root);
 
    }
    return 0;
}

B - The order of a Tree

bst树的创建,虽然不知道它有什么用。。。

 创建的时候每一次都是从根【总根】开始判断

#include<iostream>
#include<set>
#define N  100001

using namespace std;
set<int>order;
int k,ii;	
int n;
struct node
{
	node* l;
	node* r;
	int date;
	node(int date,node *l=NULL,node *r=NULL):date(date),l(l),r(r){}
};
void create(node* &root,int val)
{
	if(!root)
	{
		root =new node(val);	
	}
	else if(val<root->date)
	{
		create(root->l,val); 
	}
	else
	{
		create(root->r,val);
	}
	
}
void preorder(node *root)
{
	if(root)
	{
		printf("%d%c",root->date,ii==n-1 ? '\n':' ');
		++ii;
		preorder(root->l);
		preorder(root->r); 
	}
}
int main()
{

	node *root;
	root=NULL;
	cin>>n;
	int temp;
	for(int i=0;i<n;++i)
	{
		scanf("%d",&temp);
		create(root,temp);
	}
	preorder(root);
	return 0;
} 

 C - 二叉搜索树

#include<iostream>
#include<cstring>
using namespace std;
#define MAX 200
char tree1[MAX],tree2[MAX],n;
string s;
void create_tree(char tree[],char node)
{
	int root=1;
	while(tree[root]!='\0')
	{
		if(node < tree[root]) {	root*=2; 	}
		else 		{	root*=2; root++;		}
	}
	tree[root] = node;
}
int main()
{
	while(scanf("%d",&n)&&n) 
	{
		cin>>s;
		memset(tree1,0,sizeof(tree1));
		for(int i=0;i<s.length();++i)create_tree(tree1,s[i]);
		for(int i=0;i<n;++i)
		{
			cin>>s;
			memset(tree2,0,sizeof(tree2));
			for(int i=0;i<s.length();++i) create_tree(tree2,s[i]);
			if(memcmp(tree1,tree2,sizeof(tree1))==0) cout<<"YES\n";
			else cout<<"NO\n";
		}		
	}
	return 0;	
} 

D - Hardwood Species

 POJ - 2418 

#include<iostream>
#include<cstring>
#include<map>
#include<stdio.h>
using namespace std;
#define MAX 200
string s;
int main()
{
	map<string,int>mp;
	int num=0;
	while(getline(cin,s)!=NULL){	mp[s]++;num++; } 
	map<string,int>::iterator i;
	for(i=mp.begin();i!=mp.end();++i)
	{
		cout<<i->first;printf(" %.4f\n",i->second*100.0/num);
	}
	return 0;	
}

E - Lost Cows 

POJ - 2182  

#include<iostream>
#include<cstdio>
/**
二叉查找树:(又:二叉搜索树,二叉排序树)
	它或者是一棵空树,或者是二叉树: 
	若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 
	若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
线段树: 
	是一种二叉搜索树,与区间树相似,
	它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点
分析: 剩下的数中 
有n个数比他小,那么这个数的值是【拿去后的数中】n+1  
*/ 
using namespace std;
const int maxn=10000;
int small[maxn],ans[maxn];
struct node{
    int lc,rc,len;
};
node tree[maxn*3];//这里一开始数组开小了出现了rte 
void build(int x,int lc,int rc)//构造一棵线段树 
{
    tree[x].lc=lc,tree[x].rc=rc;//记录区间的端点值 
    tree[x].len=rc-lc+1;//记录区间长 
    if(lc==rc)return ;
    build(x*2,lc,(lc+rc)/2);//构造左子树 
    build(x*2+1,(lc+rc)/2+1,rc);//构造右子树 
}
int query(int base,int k)
{
    tree[base].len--;//代表有数被拿走,这个区间的长度自减 
    if(tree[base].lc==tree[base].rc)return tree[base].lc;//当左右子树的端点值一样的时候戴白哦达到了叶子 
    if(k<=tree[base*2].len)// 区间的长度代表了数的个数 
	{
        return query(base*2,k);//左边 
    }
    else
	{
        return query(base*2+1,k-tree[base*2].len);//右边 
    }
}
int main(void)
{
    int n;
    scanf("%d",&n); 
	small[1]=0;
    for(int i=2;i<=n;i++)//输入数据 
	{
        scanf("%d",&small[i]);
    }
    build(1,1,n);//建线段树 1-n从小到大
    for(int i=n;i>=1;i--)//从后往前找 
	{
        ans[i]=query(1,small[i]+1);//从根开始,找区间长度为的small[i]+1
    }
    for(int i=1;i<=n;i++)
	{
        printf("%d\n",ans[i]);
    }
    return 0;
}

F - Mayor's posters 

POJ - 2528[lazy] 

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define md(l,r) (l+r)>>1
#define rson(x) x<<1|1
#define lson(x) x<<1
#define endl '\n'
#define sc(x) scanf("%d",&x)
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int size=1e5+5;
int Ledge[size],Redge[size];//放端点的 
int lid[size],rid[size];
vector<int > V;
typedef long long LL;
struct node 
{
	int l,r;
	LL sum;
	LL tag;
} tree[size<<2];
void build(int k,int l,int r) 
{
	tree[k].l=l,tree[k].r=r;
	if(l==r)
	{
		tree[k].sum=0;
		return ;
	}
	int mid(md(l,r));
	build(lson(k),l,mid);
	build(rson(k),mid+1,r);
}
void change(int k) 
{
	if(tree[k].l!=tree[k].r) 
	{
		int ls=lson(k),rs=rson(k);
		tree[ls].sum=tree[k].tag;
		tree[rs].sum=tree[k].tag;
		tree[ls].tag=tree[k].tag;
		tree[rs].tag=tree[k].tag;
	}
	tree[k].tag=0;
}
void Print()
{
	for(int i=0;i<20;++i)
	{
		cout<<i<<":"<<tree[i].l<<","<<tree[i].r<<","<<tree[i].sum<<","<<tree[i].tag<<endl;
	}
 } 
int query(int k,int l,int r)
{
	LL ans=inf;
	if(tree[k].tag) change(k);//如果已经被染过色了,端点染色然后初始化 
	if(tree[k].l==l&&tree[k].r==r) 
	{
		return tree[k].sum;
	}
	int mid=md(tree[k].l,tree[k].r);
	if(r<=mid) ans=query(lson(k),l,r);//小区间在左边 
	else if(l>=mid+1) ans=query(rson(k),l,r);//小区间在右边 
	else ans=min(query(lson(k),l,mid),query(rson(k),mid+1,r));//mid在小区间内就把小区间分割 
	return ans;
}
void add(int k,int l,int r,LL x) 
{
	
	if(tree[k].tag) change(k);//端点染色判断 
	if(tree[k].l==l&&tree[k].r==r) 
	{
		tree[k].sum=x;//区间内部涂色 
		tree[k].tag=x;//tag用来记录这个区间属于哪个小区间 
		return ;
	}

	int mid=md(tree[k].l,tree[k].r);
	if(l>=mid+1) add(rson(k),l,r,x);
	else if(r<=mid) add(lson(k),l,r,x);
	else add(lson(k),l,mid,x),add(rson(k),mid+1,r,x);
	tree[k].sum=min(tree[lson(k)].sum,tree[rson(k)].sum);//从左右端点选着那个小的作为这个区间的颜色 
}

int main() 
{
	int t;sc(t);
	int ans=0;
	while(t--)
	{
		int n;
		ans=0;
		V.clear();
		memset(tree,0,sizeof(tree));
		sc(n);
		for(int i=0; i<n; i++) 
		{
			sc(Ledge[i]),sc(Redge[i]);//输入左右端点 
			V.push_back(Ledge[i]),V.push_back(Redge[i]);
		}
		sort(V.begin(),V.end());//建立数组 
		V.erase(unique(V.begin(),V.end()),V.end());//离散化——建新的数组 
		/*
		iterator erase( iterator _First, iterator _Last);
			删除从_First开始到_Last位置(不包括_Last位置)的元素
			返回值也是一个迭代器,指向最后一个删除元素的下一个位置。
		unique函数的功能:”删除”序列中所有相邻的重复元素(只保留一个)。
			此处的删除,并不是真的删除,而是指重复元素的位置被不重复的元素给占领了
	   */ 
	   
		for(int i=0; i<n; i++) lid[i]=lower_bound(V.begin(),V.end(),Ledge[i])-V.begin()+1; //离散化——绑定新的区间 
		for(int i=0; i<n; i++) rid[i]=lower_bound(V.begin(),V.end(),Redge[i])-V.begin()+1;
		/*
		lower_bound():int t=lower_bound(a+l,a+r,m)-a
			在升序排列的a数组内二分查找[l,r)区间内的值为m的元素。
			返回m在数组中的下标
		*/
		build(1,1,V.size()+1);//建线段树 
		for(int i=n-1; i>=0; i--) //倒着来 
		{
			if(query(1,lid[i],rid[i])==0) //传入一个区间和根  
			{
				add(1,lid[i],rid[i],i);
				ans++;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

G - A Simple Problem with Integers 

POJ - 3468 [lazy]

#include<iostream>
#include<stdio.h>
using namespace std;
typedef long long ll ;
const int N=1e5+10;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Node
{
	int l,r;
	int mid()
	{		return (l+r)>>1;    }	
}tree[N<<2];
ll sum[N<<2],add[N<<2];
void PushUp(int rt)
{
	sum[rt] = sum[rt<<1]+sum[rt<<1|1];
 } 
void PushDown(int rt,int m)
{
	if(add[rt])
	{
		add[rt<<1]+=add[rt];//左右节点添加延迟修改量,有可能有多个延迟修改量,这里用+= 
		add[rt<<1|1]+=add[rt];
		sum[rt<<1]+=add[rt]*(m-(m>>1));
		sum[rt<<1|1]+=add[rt]*(m>>1);
		add[rt]=0; 
	}
}
void build(int l,int r,int rt) 
{
	tree[rt].l=l;
	tree[rt].r=r;
	add[rt]=0;
	if(l==r)
	{
		scanf("%I64d",&sum[rt]);return;
	}
	int m=tree[rt].mid();
	build(lson) ;
	build(rson) ;
	PushUp(rt);
}
void update(int c,int l,int r,int rt)
{
	if(tree[rt].l==l&&tree[rt].r==r)
	{
		add[rt]+=c;//给父节点打上一个lazy标签,子节点看情况修改 
		sum[rt]+=(ll)c*(r-l+1);
		return; 
	}
	if(tree[rt].l==tree[rt].r) return;
	PushDown( rt , tree[rt].r - tree[rt].l + 1);
	int m=tree[rt].mid();
	if(r<=m) update(c,l,r,rt<<1);	
	else if(l>m) update(c,l,r,rt<<1|1);
	else
	{
		update(c,lson);	
		update(c,rson);
	}
	PushUp(rt);
}
ll query(int l,int r,int rt) 
{
	if(l==tree[rt].l&&r==tree[rt].r) return sum[rt];
	PushDown(rt,tree[rt].r-tree[rt].l+1);//一层 
	int m=tree[rt].mid();
	ll res = 0;
	if(r<=m) res+=query(l,r,rt<<1);
	else if(l>m) res+=query(l,r,rt<<1|1);
	else
	{
		 res+=query(lson);
		 res+=query(rson);
	}
 	return res;
}
int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m))
	{
		build(1,n,1);
		while(m--)
		{
			char ch[2];
			scanf("%s",ch);
			int a,b,c;
			if(ch[0]=='Q')
			{
				scanf("%d%d",&a,&b);
				printf("%lld\n",query(a,b,1));
			}
			else
			{
				scanf("%d%d%d",&a,&b,&c);
				update(c,a,b,1);
			} 
		}
	}
	return 0;	
} 

H - 敌兵布阵

 HDU - 1166 

#include<iostream>
#include<cstring>
#include<stdio.h>
using namespace std;
typedef long long ll ;
const int N=1e5+10;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Node
{
    int l,r;
    int mid()
    {       return (l+r)>>1;    }
}tree[N<<2];
ll sum[N<<2],add[N<<2];
void PushUp(int rt)
{
    sum[rt] = sum[rt<<1]+sum[rt<<1|1];
}
void Init()
{
	memset(sum,0,sizeof(N<<2));
	memset(add,0,sizeof(N<<2));
	memset(tree,0,sizeof(N<<2));
}
void build(int l,int r,int rt)
{
    tree[rt].l=l;tree[rt].r=r;
    if(l==r)
    {
        scanf("%I64d",&sum[rt]);return;
    }
    int m=tree[rt].mid();
    build(lson) ; build(rson) ;
    PushUp(rt);
}
void update(int c,int l,int r,int rt)
{
    if(tree[rt].r==tree[rt].l) 
	{
		sum[rt]+=c;
		return;
	}
    int m=tree[rt].mid();
    if(r<=m) update(c,l,r,rt<<1); 
    else if(l>m) update(c,l,r,rt<<1|1);
    else
    {
        update(c,lson);
        update(c,rson);
    }
    PushUp(rt);
}
ll query(int l,int r,int rt)
{
    if(l==tree[rt].l&&r==tree[rt].r) return sum[rt];
    int m=tree[rt].mid();ll res = 0;
    if(r<=m) res+=query(l,r,rt<<1);
    else if(l>m) res+=query(l,r,rt<<1|1);
    else
    {
         res+=query(lson);
         res+=query(rson);
    }
    return res;
}
int main()
{
    int T,N;scanf("%d",&T);
    for(int i=1;i<=T;++i)
    {
    	scanf("%d",&N);build(1,N,1);
        string ch;
        int a,b,c; 
		printf("Case %d:\n",i);
        do
        {
        	cin>>ch;
			if(ch=="Query")
	        {
	            scanf("%d%d",&a,&b);
	            printf("%lld\n",query(a,b,1));
	        }
	        else if(ch=="Add")
	        {
	            scanf("%d%d",&a,&b);
	            update(b,a,a,1);
	        }
	        else if(ch=="Sub")
			{
	        	scanf("%d%d",&a,&b);
	            update(-b,a,a,1);
			}
		}while(ch!="End");
		Init();
    }
    return 0;  
}

I - Minimum Inversion Number

 HDU - 1394 

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 5555
#define inf 99999999
int a[maxn];
struct node{
	int l,r,sum;//sum记录区间长 
}tree[maxn*4];
int ans=0;
void pushup(int v)
{
	tree[v].sum=tree[v<<1].sum+tree[v<<1|1].sum;
}
void build(int l,int r,int v)
{
	tree[v].l=l;tree[v].r=r;tree[v].sum=0;
	if(l==r) return;
	int mid=(l+r)/2;
	build(l,mid,v<<1);
	build(mid+1,r,v<<1|1);
}
int query(int l,int r,int v)//求区间长度 
{
	if(l==tree[v].l&&r==tree[v].r) return tree[v].sum;
	int mid=(tree[v].l+tree[v].r)/2;
	if(r<=mid) return query(l,r,v<<1);
	else if(l>mid) return query(l,r,v<<1|1);
	else
	{
		return query(l,mid,v<<1)+query(mid+1,r,v<<1|1);
	}
}
void update(int pos,int v)//更新区间长度 
{
	if(tree[v].l==tree[v].r){  tree[v].sum=1;return ; }
	int mid=(tree[v].l+tree[v].r)/2;
	if(pos<=mid) update(pos,v<<1);
	else update(pos,v<<1|1);
	pushup(v);
}
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		memset(a,0,sizeof(a));
		for(int i=0;i<n;i++) scanf("%d",&a[i]);
		build(0,n-1,1);
		int sum=0,min1=inf;
		for(int i=0;i<n;i++)
		{
			ans=query(a[i],n-1,1);//计算a[i]对应的逆序数个数 =大于它的且已经出现过的数的个数
			sum+=ans;
			update(a[i],1);//将a[i]标记到数列中 	
		}
		for(int i=0;i<n;i++)
		{
			sum+=n-(a[i]+1)-a[i];
			if(sum<min1) min1=sum;
		}
		printf("%d\n",min1);
	}
}

J - Just a Hook

 HDU - 1698 

 

 

 

 

 

  

 

posted @ 2019-12-08 09:33  东坡肉肉君  阅读(268)  评论(0编辑  收藏  举报