首页 > 其他分享 >奇技淫巧:Lambda表达式

奇技淫巧:Lambda表达式

时间:2023-08-15 20:11:38浏览次数:35  
标签:rs int sum define add ls Lambda 表达式 奇技淫巧

最近学习到的奇技淫巧:Lambda表达式,将函数包括递归函数改为Lambda表达式写法,可节省大量时间,在大量调用下可能节省近一半时间。

说明

该语法过于复杂,见https://en.cppreference.com/w/cpp/language/lambda,本文仅写在算法竞赛下的应用。

该语法在OIWiki中有所提及,但是十分抽象,而这里将给出的简单易懂的用法,可能不太全面,在算法竞赛中已经够用了。

有关该语法是否可用问题:关于NOI系列活动中编程语言使用限制的补充说明,这表明NOI系列比赛中(包括noip,csp)已经开始使用C++14标准,而该表达式在C++11中就已经支持

具体用法:

无自身递归调用

auto 函数名 = [&](参数) -> 函数类型 { 内容 };

给定 x 、y, 求x + y

一般写法

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

int sum(int x, int y)
{
	return x + y;
}

int main()
{
	int x, y;
	cin >> x >> y;
	cout << sum(x, y);
}

Lambda表达式写法

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

int main()
{
	auto sum = [&](int x, int y) -> int 
	{
		return x + y;
	};//注意这里的分号
	int x, y;
	cin >> x >> y;
	cout << sum(x, y);
}

有自身函数调用

注意:如果函数内存在对自生的调用,按上述写法是无法编译的,我们需要这样写:

int main()
{
	auto 函数名 = [&](参数, auto&& self) -> 函数类型
	{ 
		//内容 
		//对自身调用时:
		self(参数, self);
	};
	//主函数内调用:
	函数名(参数, 函数名);//举例 : int d = gcd(x, y, gcd);
};

gcd函数

Lambda表达式写法

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

int main()
{
	auto gcd = [&](int x, int y, auto&& self) -> int 
	{
		if(y == 0) return x;
		else return self(y, x % y, self);
	};//注意这里的分号
	int x, y;
	cin >> x >> y;
	cout << gcd(x, y, gcd);
}

线段树

题目luogu线段树1

一般代码

// Problem: P3372 【模板】线段树 1
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3372
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define ll long long
#define MAXn 100010
#define ls(x) tr[x].ls
#define rs(x) tr[x].rs
#define sum(x) tr[x].sum
#define add(x) tr[x].add
#define l(x) tr[x].l
#define r(x) tr[x].r
#define sz(x) tr[x].sz
#define mid(x) tr[x].mid
using namespace std;

int n, m;
int a[MAXn];

struct SegmentTree
{
	ll ls, rs, l, r, sum, add, sz, mid;
} tr[MAXn << 2];

ll read()
{
	ll num = 0, w = 1;
	char ch = getchar();
	while(ch > '9' || ch < '0') { if(ch == '-') w = -1; ch = getchar(); }
	while(ch <= '9' && ch >= '0') { num = (num << 3) + (num << 1) + (ch - '0');	ch = getchar(); }
	return num * w;
}

void build(int ind, int L, int R)
{
	l(ind) = L;
	r(ind) = R;
	sz(ind) = R - L + 1;
	mid(ind) = (L + R) >> 1;
	if(L == R)
	{
		sum(ind) = a[L];
		return;
	}
	ls(ind) = ind << 1;
	rs(ind) = ind << 1 | 1;
	int mid = (L + R) >> 1;
	build(ls(ind), L, mid);
	build(rs(ind), mid + 1, R);
	sum(ind) = sum(ls(ind)) + sum(rs(ind));
}

void pushdown(int x)
{
	if(add(x))
	{
		sum(ls(x)) += add(x) * sz(ls(x));
		sum(rs(x)) += add(x) * sz(rs(x));
		add(ls(x)) += add(x);
		add(rs(x)) += add(x);
		add(x) = 0;
	}
}

void update(int x, int L, int R, ll k)
{
	if(L <= l(x) && R >= r(x))
	{
		sum(x) += sz(x) * k;
		add(x) += k;
		return;
	}
	pushdown(x);
	if(L <= mid(x)) update(ls(x), L, R, k);
	if(R >= mid(x) + 1) update(rs(x), L, R, k);
	sum(x) = sum(ls(x)) + sum(rs(x));
}

ll ask(int x, int L, int R)
{
	if(L <= l(x) && R >= r(x))
	{
		return sum(x);
	}
	pushdown(x);
	ll res = 0;
	if(L <= mid(x)) res += ask(ls(x), L, R);
	if(R >= mid(x) + 1) res += ask(rs(x), L, R);
	return res;
}

int main()
{
	n = read(), m = read();
	for(int i = 1; i <= n; i++)
		a[i] = read();
	build(1, 1, n);
	while(m--)
	{
		ll flag, x, y;
		flag = read(), x = read(), y = read();
		if(flag == 1)
		{
			ll k;
			k = read();
			update(1, x, y, k);
		}
		else 
		{
			printf("%lld\n", ask(1, x, y));
		}
	}
	return 0;
}

Lambda代码

// Problem: P3372 【模板】线段树 1
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3372
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define ll long long
#define MAXn 100010
#define ls(x) tr[x].ls
#define rs(x) tr[x].rs
#define sum(x) tr[x].sum
#define add(x) tr[x].add
#define l(x) tr[x].l
#define r(x) tr[x].r
#define sz(x) tr[x].sz
#define mid(x) tr[x].mid
using namespace std;

int n, m;
int a[MAXn];

struct SegmentTree
{
	ll ls, rs, l, r, sum, add, sz, mid;
} tr[MAXn << 2];

int main()
{
	
	auto read = [&]() -> ll
	{
		ll num = 0, w = 1;
		char ch = getchar();
		while(ch > '9' || ch < '0') { if(ch == '-') w = -1; ch = getchar(); }
		while(ch <= '9' && ch >= '0') { num = (num << 3) + (num << 1) + (ch - '0');	ch = getchar(); }
		return num * w;
	};
	auto build = [&](int ind, int L, int R, auto&& self) -> void
	{
		l(ind) = L;
		r(ind) = R;
		sz(ind) = R - L + 1;
		mid(ind) = (L + R) >> 1;
		if(L == R)
		{
			sum(ind) = a[L];
			return;
		}
		ls(ind) = ind << 1;
		rs(ind) = ind << 1 | 1;
		int mid = (L + R) >> 1;
		self(ls(ind), L, mid, self);
		self(rs(ind), mid + 1, R, self);
		sum(ind) = sum(ls(ind)) + sum(rs(ind));
	};
	auto pushdown = [&](int x) -> void
	{
		if(add(x))
		{
			sum(ls(x)) += add(x) * sz(ls(x));
			sum(rs(x)) += add(x) * sz(rs(x));
			add(ls(x)) += add(x);
			add(rs(x)) += add(x);
			add(x) = 0;
		}
	};
	auto update = [&](int x, int L, int R, ll k, auto&& self) -> void 
	{
		if(L <= l(x) && R >= r(x))
		{
			sum(x) += sz(x) * k;
			add(x) += k;
			return;
		}
		pushdown(x);
		if(L <= mid(x)) self(ls(x), L, R, k, self);
		if(R >= mid(x) + 1) self(rs(x), L, R, k, self);
		sum(x) = sum(ls(x)) + sum(rs(x));
	};
	auto ask = [&](int x, int L, int R, auto&& self) -> ll
	{
		if(L <= l(x) && R >= r(x))
		{
			return sum(x);
		}
		pushdown(x);
		ll res = 0;
		if(L <= mid(x)) res += self(ls(x), L, R, self);
		if(R >= mid(x) + 1) res += self(rs(x), L, R, self);
		return res;
	};

	n = read(), m = read();
	for(int i = 1; i <= n; i++)
		a[i] = read();
	build(1, 1, n, build);
	while(m--)
	{
		ll flag = read(), x = read(), y = read();
		if(flag == 1)
		{
			ll k;
			k = read();
			update(1, x, y, k, update);
		}
		else 
		{
			printf("%lld\n", ask(1, x, y, ask));
		}
	}
	return 0;
}

时间比较

  • 一般做法

image

  • Lambda表达式

image

标签:rs,int,sum,define,add,ls,Lambda,表达式,奇技淫巧
From: https://www.cnblogs.com/six-one/p/17632324.html

相关文章

  • 代码随想录算法训练营第十一天|力扣20.有效的括号、力扣1047.删除字符串中所有相邻重
    有效的括号(力扣20.)括号匹配时使用栈解决的经典问题题意其实就像我们在写代码的过程中,要求括号的顺序是一样的有左括号,那么在对应位置则必须有右括号第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以returnfalse第二种情况:遍历字......
  • 正则表达式
    正则表达式(regularexpression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种我们所需要的子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。  JavaScript和Java使用正则表达式的区别JavaScript使用正则表达式创建正则对象RegExp对......
  • 正则表达式
    转载自:https://zhuanlan.zhihu.com/p/33683962一、校验数字的表达式数字:^[0-9]*$n位的数字:^d{n}$至少n位的数字:^d{n,}$m-n位的数字:^d{m,n}$零和非零开头的数字:^(0|[1-9][0-9]*)$非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$带1-2位小数的正数或负数:^(-......
  • Linux之shell脚本的正则表达式
    目录一、正则表达式1.1元字符1.2表示次数一、正则表达式通配符功能是用来处理文件名,而正则表达式是处理文本内容中字符[localhost~]#man7regex#可以使用man手册帮助1.1元字符. 匹配任意单个字符,可以是一个汉字[] 匹配指定范围内的任意单个字符,示例:[zhou]......
  • 4 表达式
    =赋值运算符优先级较低,赋值运算符满足右结合律*p++相当于*(p++) p++++p不同的行为值得注意以下情况可能发生类型转换:比int类型小的整数值首先提升为较大的整数类型;函数调用时;算数运算时;初始化时;显示类型转换static_castconst_castreinterpret_caststatic_cast......
  • 分治算法——241. 为运算表达式设计优先级
    分治思路:对于一个算式来说,总是可以根据运算符分为左右两部分算式,接着分别计算结果并合并;每一个结果都是一个数组,包含这个算式的所有可能结果,计算时将左右两部分排列组合;递归的终点是字符串是纯数字(即分到一个算式中只剩下一个数字),直接返回。 比如示例中的2*3-4*5,有下面的......
  • JDK1.8 Lambda & Stream
    JDK1.8Lambda&Stream参考链接: https://www.cnblogs.com/CarpenterLee/p/6637118.html#4486817 https://www.cnblogs.com/CarpenterLee/p/6675568.html https://blog.csdn.net/xiliunian/article/details/88343762 https://blog.csdn.net/xiliunian/article/detail......
  • 深入理解JavaScript正则表达式:释放其强大力量
    深入理解JavaScript正则表达式:释放其强大力量正则表达式是一种强大的工具,用于在字符串中搜索、匹配和替换特定的模式。在JavaScript中,正则表达式是一种内置的功能,可以帮助开发人员处理各种字符串操作。本文将深入探讨JavaScript正则表达式的原理、语法和应用场景,帮助读者充分理解......
  • 表达式树
    这节来讲一下C#中的表达式树(又称表达式目录树、Expression)。什么是表达式树? 表达式树是一种C#中的数据结构,它以树的形式表示某些代码内部的结构。每个节点是一种称为表达式的C#对象,例如二元运算,方法调用,常量等。这种数据结构主要用于LINQ查询的内部机制和动态编程。在C#中,表......
  • lambda表达式(jdk8才开始出现的语法)
    1、是为了简化某些场景下匿名对象的繁琐。其中有一种函数式编程(强调做什么,而不是强调谁去做)的思想。语法格式:(形参列表)->(固定格式){​ 方法体;}测试代码如下所示:importjava.util.Arrays;importjava.util.Comparator;publicclassTest{publicstaticvoidmain(S......