模板(acm)

加权并查集:
// http://poj.org/problem?id=1182
#include

struct node
{
	int p;
	int r;
}a[50005];

int find(int x)
{
	if(x==a[x].p) return x;
	
	int t=a[x].p;
	a[x].p=find(t);
	a[x].r=(a[x].r+a[t].r)%3;
	return a[x].p;
}

int main()
{
	int N,k;
	scanf("%d%d",&N,&k);
	
	int i,j,d,x,y,ans=0;
	
	for(i=1;i<=N;i++)
	{
		a[i].p=i;
		a[i].r=0;
	}
	
	for(i=0;iN||y>N) ans++;
		else
		{
			if(d==2&&x==y) ans++;
			else
			{
				int c=find(x);
				int b=find(y);
				
				if(c!=b)
				{
					a[b].p=c;
					a[b].r=(3+d-1+a[x].r-a[y].r)%3; 
				}
				else
				{
					if(d==2&&((3-a[x].r+a[y].r)%3!=d-1)) ans++;
					if(d==1&&a[x].r!=a[y].r) ans++;
				}
			}
		}
	}
	printf("%d\n",ans);
	
	return 0;
}





线段树(单点更新,区间求和)
//http://acm.hdu.edu.cn/showproblem.php?pid=1754
#include
#include
#include

using namespace std;

const int N=200000+5;

struct Node
{
	int left,right;
	int value;
};

Node tree[N<<2];
int father[N<<2];

void BuiltTree(int l,int r,int i)
{
	tree[i].value=0;
	tree[i].right=r;
	tree[i].left=l;
	
	if(l==r)
	{
		father[l]=i;
	//	printf("f %d %d %d\n",father[l],i,l);
		return ;
	}
	BuiltTree(l,(int)(floor)(l+r)/2,i<<1);
	BuiltTree((int)(floor)(l+r)/2+1,r,(i<<1)+1);
}

void Update(int i)
{
	i>>=1;
	if(i==0) return ;
	tree[i].value=max(tree[i<<1].value,tree[(i<<1)+1].value);
//	printf("%d %d %d %d\n",i,tree[i].value,tree[i<<1].value,tree[(i<<1)+1].value);
	Update(i);
}

int ans;

void query(int l,int r,int i)
{
	if(l==tree[i].left && r==tree[i].right)
	{
		ans=max(tree[i].value,ans);
		return ;
	}
	
	i<<=1;
	if(l<=tree[i].right)
	{
		if(r<=tree[i].right)
			query(l,r,i);
		else query(l,tree[i].right,i);
	}
	i++;
	if(r>=tree[i].left)
	{
		if(l>=tree[i].left) query(l,r,i);
		else query(tree[i].left,r,i);
	}
}

int main()
{
	int n,m;
	
	while(~scanf("%d%d",&n,&m))
	{
		BuiltTree(1,n,1);
		int i=1;
		while(i<=n)
		{
			scanf("%d",&tree[father[i]].value);
			Update(father[i]);
		//	printf("%d \n",tree[father[i]].value);
			i++;
		}
		while(m--)
		{
			char a[2];
			int v;
			scanf("%s%d%d",a,&i,&v);//printf("%c %d\n",a[0],father[i]);
			if(a[0]=='U')
			{
			//	printf("v%d %d\n",father[i],tree[father[i]].value);
				tree[father[i]].value=v;
			//	printf("v%d %d\n",father[i],tree[father[i]].value);
				Update(father[i]);
			}
			else
			{
				ans=0;
				query(i,v,1);
				printf("%d\n",ans);
			}
		}
	}
	
	return 0;
}

区间线段树(区间修改,区间求和)
// http://poj.org/problem?id=3468
#include
#define ll long long
const int N=100000;

struct Node
{
	int l,r;
	
	int mid()
	{
		return (l+r)>>1;
	}
}tree[N<<2];

ll sum[N<<2],add[N<<2];

void pushup(int i){sum[i]=sum[i<<1]+sum[i<<1|1];}

void pushdown(int i,int m)
{
	if(add[i])
	{
		add[i<<1]+=add[i];
		add[i<<1|1]+=add[i];
		sum[i<<1]+=add[i]*(m-(m>>1));
		sum[i<<1|1]+=add[i]*(m>>1);
		add[i]=0;
	}
}

void buildtree(int l,int r,int i)
{
	tree[i].l=l;
	tree[i].r=r;
	add[i]=0;

	if(l==r)
	{
		scanf("%lld",&sum[i]);
	//	printf("%d %d %d\n",i,sum[i],l);
		return ;
	}

	int m=tree[i].mid();
	buildtree(l,m,i<<1);
	buildtree(m+1,r,i<<1|1);
	pushup(i);
}

void update(int l,int r,int i,ll w)
{
	if(tree[i].l==l&&tree[i].r==r)
	{
		sum[i]+=(ll)w*(tree[i].r-tree[i].l+1);
		add[i]+=w;
		return ;
	}
	if(tree[i].l==tree[i].r) return ;
	pushdown(i,tree[i].r+1-tree[i].l);
	
	int m=tree[i].mid();
	if(l>m) update(l,r,i<<1|1,w);
	else if(r<=m) update(l,r,i<<1,w);
	else
	{
		update(l,m,i<<1,w);
		update(m+1,r,i<<1|1,w);
	}
	pushup(i);
}

ll ans;
ll query(int l,int r,int i)
{
	if(tree[i].l==l&&tree[i].r==r)
	{
		return sum[i]+ans;
	}

	pushdown(i,tree[i].r+1-tree[i].l); 
	int m=tree[i].mid();
	if(l>m) ans=query(l,r,i<<1|1);
	else if(r<=m) ans=query(l,r,i<<1);
	else
	{
		ans=query(l,m,i<<1);
		ans=query(m+1,r,i<<1|1);
	}

	return ans;
}

int main()
{
	int n,q,l,r,w;
	
	scanf("%d%d",&n,&q);
	buildtree(1,n,1);

	while(q--)
	{
		char a[2];
		getchar();
		scanf("%s",a);
		if(a[0]=='Q')
		{
			scanf("%d%d",&l,&r);
			ans=0;
			printf("%lld\n",query(l,r,1));
		}
		else
		{
			scanf("%d%d%d",&l,&r,&w);
			update(l,r,1,w);
		}
	}
	
	return 0;
}








STL
一.Algorithm

给定一个vector容器:vector nums={8,7,5,4,2,9,6,1,3,0};
find:find(nums.begin(),nums.end(),4); 
find the number 4 ,return the iterator of the number。 
返回第一次出现4的位置的迭代器(可以理解为指针,但不同。) 
想要得到4所在位置的下标,可以写作 
find(nums.begin(),nums.end(),4)-nums.begin(); 
注:若未找到则返回nums.end()

swap:swap(nums[0],nums[2]); 
交换nums中下标为0和下标为2的元素。
for_each:for_each(nums.begin(),nums.end(),[](int n){cout< #include  #include  
using namespace std; 
int main() 
{
vectornums={8,7,5,4,2,9,6,1,3,0}; 	cout<n2;}); 	for_each(nums.begin(),nums.end(),[](int n){cout<::iterator it;  it=adjacent_find(nums.begin(),nums.end() );
all_of C++11	检测在给定范围中是否所有元素都满足给定的条件bool flag= std::all_of(nums.begin(), nums.end(),[](int i);

any_of C++11	检测在给定范围中是否存在元素满足给定条件
count	返回值等价于给定值的元素的个数
count_if	返回值满足给定条件的元素的个数
equal	返回两个范围是否相等
find	返回第一个值等价于给定值的元素
find_end	查找范围A中与范围B等价的子范围最后出现的位置
find_first_of	查找范围A中第一个与范围B中任一元素等价的元素的位置
find_if	返回第一个值满足给定条件的元素
find_if_notC++11	返回第一个值不满足给定条件的元素
for_each	对范围中的每个元素调用指定函数
mismatch	返回两个范围中第一个元素不等价的位置
none_ofC++11	检测在给定范围中是否不存在元素满足给定的条件
search	在范围A中查找第一个与范围B等价的子范围的位置
search_n	在给定范围中查找第一个连续n个元素都等价于给定值的子范围的位置
修改内容的序列操作:
copy	将一个范围中的元素拷贝到新的位置处
copy_backward	将一个范围中的元素按逆序拷贝到新的位置处
copy_ifC++11	将一个范围中满足给定条件的元素拷贝到新的位置处
copy_nC++11	拷贝 n 个元素到新的位置处
fill	将一个范围的元素赋值为给定值
fill_n	将某个位置开始的 n 个元素赋值为给定值
generate	将一个函数的执行结果保存到指定范围的元素中,用于批量赋值范围中的元素
generate_n	将一个函数的执行结果保存到指定位置开始的 n 个元素中
iter_swap	交换两个迭代器(Iterator)指向的元素
moveC++11	将一个范围中的元素移动到新的位置处
move_backwardC++11	将一个范围中的元素按逆序移动到新的位置处
random_shuffle	随机打乱指定范围中的元素的位置
remove	将一个范围中值等价于给定值的元素删除
remove_if	将一个范围中值满足给定条件的元素删除
remove_copy	拷贝一个范围的元素,将其中值等价于给定值的元素删除
remove_copy_if	拷贝一个范围的元素,将其中值满足给定条件的元素删除
replace	将一个范围中值等价于给定值的元素赋值为新的值
replace_copy	拷贝一个范围的元素,将其中值等价于给定值的元素赋值为新的值
replace_copy_if	拷贝一个范围的元素,将其中值满足给定条件的元素赋值为新的值
replace_if	将一个范围中值满足给定条件的元素赋值为新的值
reverse	反转排序指定范围中的元素
reverse_copy	拷贝指定范围的反转排序结果
rotate	循环移动指定范围中的元素
rotate_copy	拷贝指定范围的循环移动结果
shuffleC++11	用指定的随机数引擎随机打乱指定范围中的元素的位置
swap	交换两个对象的值
swap_ranges	交换两个范围的元素
transform	对指定范围中的每个元素调用某个函数以改变元素的值
unique	删除指定范围中的所有连续重复元素,仅仅留下每组等值元素中的第一个元素。
unique_copy	拷贝指定范围的唯一化(参考上述的 unique)结果
划分操作:
is_partitionedC++11	检测某个范围是否按指定谓词(Predicate)划分过
partition	将某个范围划分为两组
partition_copyC++11	拷贝指定范围的划分结果
partition_pointC++11	返回被划分范围的划分点
stable_partition	稳定划分,两组元素各维持相对顺序
排序操作:
is_sortedC++11	检测指定范围是否已排序
is_sorted_untilC++11	返回最大已排序子范围
nth_element	部份排序指定范围中的元素,使得范围按给定位置处的元素划分
partial_sort	部份排序
partial_sort_copy	拷贝部分排序的结果
sort	排序
stable_sort	稳定排序
二分法查找操作:
binary_search	判断范围中是否存在值等价于给定值的元素
equal_range	返回范围中值等于给定值的元素组成的子范围
lower_bound	返回指向范围中第一个值大于或等于给定值的元素的迭代器
upper_bound	返回指向范围中第一个值大于给定值的元素的迭代器
集合操作:
includes	判断一个集合是否是另一个集合的子集
inplace_merge	就绪合并
merge	合并
set_difference	获得两个集合的差集
set_intersection	获得两个集合的交集
set_symmetric_difference	获得两个集合的对称差
set_union	获得两个集合的并集

堆操作:
is_heap	检测给定范围是否满足堆结构
is_heap_untilC++11	检测给定范围中满足堆结构的最大子范围
make_heap	用给定范围构造出一个堆
pop_heap	从一个堆中删除最大的元素
push_heap	向堆中增加一个元素
sort_heap	将满足堆结构的范围排序
最大/最小操作:
is_permutationC++11	判断一个序列是否是另一个序列的一种排序
lexicographical_compare	比较两个序列的字典序
max	返回两个元素中值最大的元素
max_element	返回给定范围中值最大的元素
min	返回两个元素中值最小的元素
min_element	返回给定范围中值最小的元素
minmaxC++11	返回两个元素中值最大及最小的元素
minmax_elementC++11	返回给定范围中值最大及最小的元素
next_permutation	返回给定范围中的元素组成的下一个按字典序的排列
prev_permutation	返回给定范围中的元素组成的上一个按字典序的排列




Vector
初始化:
(1) vector a(10); //定义了10个整型元素的向量(尖括号中为元素类型名,它可以是任何合法的数据类型),但没有给出初值,其值是不确定的。
   (2)vector a(10,1); //定义了10个整型元素的向量,且给出每个元素的初值为1
   (3)vector a(b); //用b向量来创建a向量,整体复制性赋值
   (4)vector a(b.begin(),b.begin+3); //定义了a值为b中第0个到第2个(共3个)元素
   (5)int b[7]={1,2,3,4,5,9,8};
        vector a(b,b+7); 或者vector a(b,&b[7])//从数组中获得初值;

函数:
(1)a.assign(b.begin(), b.begin()+3); //b为向量,将b的0~2个元素构成的向量赋给a
    (2)a.assign(4,2); //是a只含4个元素,且每个元素为2
    (3)a.back(); //返回a的最后一个元素
    (4)a.front(); //返回a的第一个元素
    (5)a[i]; //返回a的第i个元素,当且仅当a[i]存在2013-12-07
    (6)a.clear(); //清空a中的元素
    (7)a.empty(); //判断a是否为空,空则返回ture,不空则返回false
    (8)a.pop_back(); //删除a向量的最后一个元素
    (9)a.erase(a.begin()+1,a.begin()+3); //删除a中第1个(从第0个算起)到第2个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+         3(不包括它)
    (10)a.push_back(5); //在a的最后一个向量后插入一个元素,其值为5
    (11)a.insert(a.begin()+1,5); //在a的第1个元素(从第0个算起)的位置插入数值5,如a为1,2,3,4,插入元素后为1,5,2,3,4
    (12)a.insert(a.begin()+1,3,5); //在a的第1个元素(从第0个算起)的位置插入3个数,其值都为5
    (13)a.insert(a.begin()+1,b+3,b+6); //b为数组,在a的第1个元素(从第0个算起)的位置插入b的第3个元素到第5个元素(不包括b+6),如b为1,2,3,4,5,9,8         ,插入元素后为1,4,5,9,2,3,4,5,9,8
    (14)a.size(); //返回a中元素的个数;
    (15)a.capacity(); //返回a在内存中总共可以容纳的元素个数
    (16)a.resize(10); //将a的现有元素个数调至10个,多则删,少则补,其值随机
    (17)a.resize(10,2); //将a的现有元素个数调至10个,多则删,少则补,其值为2
    (18)a.reserve(100); //将a的容量(capacity)扩充至100,也就是说现在测试a.capacity();的时候返回值是100.这种操作只有在需要给a添加大量数据的时候才         显得有意义,因为这将避免内存多次容量扩充操作(当a的容量不足时电脑会自动扩容,当然这必然降低性能) 
    (19)a.swap(b); //b为向量,将a中的元素和b中的元素进行整体性交换
    (20)a==b; //b为向量,向量的比较操作还有!=,>=,<=,>,<

访问vector的特殊方法
从现有向量中选择元素向向量中添加:
int a[6]={1,2,3,4,5,6};
vector b;
vector c(a,a+4);for(vector::iterator it=c.begin();it a;for(int i; in>>i)
    a.push_back(i);

从向量中读取元素得方法:
int a[6]={1,2,3,4,5,6};
vector b(a,a+4);for(int i=0;i<=b.size()-1;i++)
cout< b(a,a+4);for(vector::iterator it=b.begin();it!=b.end();it++)
    cout<<*it<<" ";

Vector的几种重要算法
1.
(1)sort(a.begin(),a.end()); //对a中的从a.begin()(包括它)到a.end()(不包括它)的元素进行从小到大排列
(2)reverse(a.begin(),a.end()); //对a中的从a.begin()(包括它)到a.end()(不包括它)的元素倒置,但不排列,如a中元素为1,3,2,4,倒置后为4,2,3,1
(3)copy(a.begin(),a.end(),b.begin()+1); //把a中的从a.begin()(包括它)到a.end()(不包括它)的元素复制到b中,从b.begin()+1的位置(包括它)开        始复制,覆盖掉原有元素
(4)find(a.begin(),a.end(),10); //在a中的从a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置

2.(使用时注意)
vector::iterator it;//迭代器 
	int i;
初始化:	
	vectorv1;        //定义空的vector
    vectorv2(10);    //产生大小为10的vector
    vectorv3(10,-1);    //产生大小为10,并且每个元素都是-1的vector
    vectorv4(v3);        //用一个vector产生一个vecotr
	
	int arr[5]={1,2,3,4,5};
    vectorv5(arr,&arr[5]);    //以区间[beg;end)做为初值的vector
    cout<a;
	vectorb; 
	a.assign(4,2);//a只包含4个元素,且每个元素都为2;
	cout<::size_type n=a.size();//Returns the number of elements in the vector.Member type size_type is an unsigned integral type.
    cout<<"a.size:"<lst1;          //创建空list
list lst2(5);       //创建含有5个元素的list
listlst3(3,2);  //创建含有3个元素的list
listlst4(lst2);    //使用lst2初始化lst4
listlst5(lst2.begin(),lst2.end());  //同lst4
操作函数

listlst1;          //创建空list
    list lst2(5);       //创建含有5个元素的list,每个元素都为0 
    listlst3(3,2);  //创建含有3个元素的list,每个元素都为2 
    listlst4(lst2);    //使用lst2初始化lst4
    listlst5(lst2.begin(),lst2.end());  //声明一个列表,其元素的初始值来源于由区间所指定的序列中的元素,
	
	list a;
	list::iterator it1,it2;
	
	赋值:
a.push_back(i);//push_back()是从list末端插入,而push_front是从头部插入
b.赋值 :a.push_front(i);

	遍历:
	for(it1=a.begin();it1!=a.end();++it1)
				printf("%d ",*it1);
			
	
a的大小 :	printf("\nsize:%d\n",a.size());// a的元素个数 
a的最大容量: 	cout<::reverse_iterator it3;

双向链表末段:	it3=a.rbegin();//返回逆向链表的第一个元素,即c链表的最后一个数据。
双向链表的头部: 	 it3=a.rend();//返回逆向链表的最后一个元素的下一个位置,即c链表的第一个数据再往前的位置。
	
	//使用pop_back()可以删掉尾部第一个元素,pop_front()可以删掉头部第一个元素。注意:list必须不为空,
	//如果当list为空的时候调用pop_back()和pop_front()会使程序崩掉。
	//使用前最好先a.empty();
删除:
 a.pop_back();
	 a.pop_front();
	
赋值:	
	a.assign(3,1);//将a变成元素个数为3,值都为1的list 
	listb;
	b.assign(a.begin(),a.end());//将b初始化,且和a相同 ,a.begin()和a.end()只能能++或者--
	int ints[]={1,2,3,4};
	a.assign(ints,ints+4);//利用数组初始化a 
	
交换:
	a.swap(b);//交换两个链表。a.swap(b)和swap(a, b),都可以完成a链表和b链表的交换。
	
转置:	
	reverse(b.begin(),b.end());
	
Empty:
	if(a.empty()) {...;}
合并:
	a.merge(b,less());//将b合并到a,less()(默认):a在前,b在后,greater则相反
	//也可以用cmp ( bool mycomparison (double first, double second)
{ return ( int(first) 0 迭代器+n, n <0 迭代器-n。

	it2++;
删除:	a.erase(it1);//删除第5个元素(a从0开始) 

	it1=a.begin();
	it2=a.begin();
	advance(it1,4);
//	a.erase(it1);//删除it1位置的元素 
//	因为a.erase()是对地址进行操作,当执行这一步时,下面erase会爆炸 
	a.erase(++it2,it1);//删除a中it2到it1-1之间的元素 
	
删除:
	list::iterator it=++a.begin();
	a.remove(1);// 删除链表中匹配num的元素。
	a.remove_if(cmp_remove);//删除条件满足的元素,参数为自定义的回调函数。
	for(it1=a.begin();it1!=a.end();++it1)
		printf("%d ",*it1);
	printf("\n");
	
去重
	for(int i=1;i<5;i++) a.push_back(0);
	a.unique();//删除相邻且重复的元素(保留一个) 
	for(it1=a.begin();it1!=a.end();++it1)
		printf("%d ",*it1);
	printf("\n");

排序
	a.sort(cmp);//排序b不能用sort(a.begin(),a.end()); 
	for(it1=a.begin();it1!=a.end();++it1)
		printf("%d ",*it1);
	printf("\n");
	
清空
	a.clear();//删除链表中匹配num的元素。
	

Queue
	queue a,b;
	//queue没有迭代器!!!!!!!!! 
	
	插入 
	a.push(1);

	删除
	a.pop();
	
	size 
	printf("%d\n",a.size());//返回值为 unsigned int
queueq;  //创建一个int型空队列q
	q.empty();   //判断队列是否为空,为空返回true
	q.push(2);   //将变量s从队尾入队
	q.pop();      //将队头元素弹出
	q.front();  // 只返回队头元素
	q.back();   //只返回队尾元素
	q.size();    // 返回队列中元素个数
	
Deque
(头文件deque)双端队列的操作  (可以在队头队尾进行入队出队操作)
	//deque有迭代器!!! 
	deque dq;   //创建一个数双端队列dq
	
	dq.empty();    //判断队列是否为空,为空返回true
	
	dq.push_front(3);   //将s从队头入队
	deque::iterator it;
	it=dq.begin();
	printf("%d\n",*it);
	dq.push_back(4);   //将s从队尾入队,和普通队列方式一样
	dq.front();    //只返回队头元素
	dq.back();    //只返回队尾元素
	dq.pop_front();    //将队头元素弹出
	dq.pop_back();    //将队尾元素弹出
	dq.clear();     //将队列清空


虽然是自己写的,但是都忘了。

你可能感兴趣的:(acm之旅(去你妹的acm),c++,标准库函数,stl容器)