欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一些实用的东西...(亲测

程序员文章站 2022-05-31 17:29:26
...

目录


废话不多说,直接切入正题

读优

.
:
这大概是我见过的码风最能接受的读优了…
总之好写好用,用就对了

	inline int read(){      
	int re=0;
    char ch=getchar();
    while (ch<'0' || ch>'9') ch=getchar();
    while (ch>='0' && ch<='9'){ 
        re=re*10+ch-'0'; 
        ch=getchar();
    }
    return re;
	}

输优

.
:
这个输优不用开数组,而且好写,所以…
当然不需要换行就把\n给干掉…

	inline void write(int x){  
    int y=10,len=1;  
    while(y<=x){
		y*=10;
		len++;
	}  
    while(len--){
		y/=10;
		putchar(x/y+48);
		x%=y;
	}
	putchar('\n');
	}

求lg

换底公式,在无理数后+1/+0.5来减少误差是个好习惯…
log2n=log(n)/log(2)+1

求n个数的lg

	for(int i=1;i<=n;i++)
		lg[i]=lg[i-1]+(1<<lg[i-1]==0);

树上前向星

树上的dfs其实可以不用打访问标记,因为只需要不让连的点为父亲就好了

	for(int i=head[u];i>-1;i=e[i].next)
		if(e[i].v!=fa)
			dfs(e[i].v,u);

流同步

关闭:ios::sync_with_stdio(false);
开启:ios::sync_with_stdio(true);

精度误差

产生原因是浮点数存储空间有限,导致无限循环数改变,这时一般需要±esp(esp=1e-8)
至于为什么是1e-8,只能说是出题人默认
a>=0–> a>-eps
a<=0–> a<eps

还有个类似的操作
利用强制类型转换模拟四舍五入

double a;
printf("%d",a+0.5);

当然也可以用下取整实现~~(然而更啰嗦~~…

#include<cmath>
int a;
double b;
printf("%d",a=floor(b+0.5));

位运算优化

判断整数奇偶: x&1
比较两数是否相等: !x^y
判断两数是否同号: !((x^y)>>31)
交换两个数:a^=b;b^=a;a^=b;
求绝对值:(n^(n>>31))-(n>>31)

双端队列

简单来说就是左端是队列,右端是栈

Floyd求最小环

dis是被k更新过的,map是未更新的,二者刚好构成环

for(int k=1;k<=n;k++)
	for(int i=1;i<=n;i++)
		for(j=1;j<=n;j++)
			ans=min(ans,map[i][k]+map[k][j]+dis[j][i];

Floyd求最短路的条数

用乘法原理更新最短路条数,分三种情况
1、当有新路径等于最短路,条数+=
2、当有新路径小于最短路,直接更新,条数=
3、新路径大于最短路,直接跳过

for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(dis[i][j]>dis[i][k]+dis[k][j])
            {
                dis[i][j]=dis[i][k]+dis[k][j];
                num[i][j]=num[i][k]*num[k][j];
            }
            if(dis[i][j]==dis[i][k]+dis[k][j])
                num[i][j]+=num[i][k]*num[k][j];
        } 

伪去重离散化

//unique(u,v)返回去重(伪)后的地址,被删掉的会加到返回值后
//bo==lower_bound(u,v,x)返回最接近x的值的地址
int const maxn=1e5+10;
int a[maxn], t[maxn];
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
    scanf("%d",a[i]),t[i]=a[i];
sort(t+1,t+n+1);//排序,找相对大小
m=unique(t+1,t+1+n)-t-1;//m为不重复的元素的个数
for(int i=1; i<=n; i++)
    a[i]=lower_bound(t+1,t+1+m,a[i])-t;//相对大小的

Cmp函数维护序列的稳定性

inline int cmp(int x,int y)
{
	return a[x]>a[y];
}
inline int cmp(int x,int y)
{
	return a[x]>=a[y];
}

上述两个cmp函数结果虽然相同
然而当遇到相同的数时
前者是按在原序列中出现的时间先后排序(时间先者先)
后者则是逆在原序列中出现的时间先后排序(时间后者先)

用前缀和维护区间大于k的值的和

for(int i=1;i<=n;i++)
	{
		if(w[i]>=ans)
			prs[i]=prs[i-1]+v[i];
		else 
			prs[i]=prs[i-1];
	}

二分的范围

l=minx,r=maxx;
能达到左界,但达不到右界
想达到右界需要
r=maxx+1;

多个long long模拟高精

乱搞即可

宏定义

没啥卵用的东西 (快乐就完事了
#define int long long

建一个命名空间防止变量重复

namespace Panther
//匿名的namespace可以当static使用
{
	//可以存类 变量 函数
	int god;
}
int main()
{
	Panther::god=true;
	//233
	return 0;
}

并没有卵用的多变量手写max

int max(int a,int b,int c,int d)
{
        return (((((a>b)?a:b)>c)?((a>b)?a:b):c)>d)?((((a>b)?a:b)>c)?((a>b)?a:b):c):d;
}

利用构造函数快速赋值

前向星的毒瘤压行写法

struct E
{
    int to,next,w;
    E(int to=0,int next=0,int w=0):
        to(to),next(next),w(w){}
}e[maxn2<<1];

void add(int u,int v,int w)
{
	e[++cnt]=(E){v,head[u],w};
	head[u]=cnt;

构造重载运算符

struct node
{
    int nd,dis;
    bool operator<(const node &b)const
    {
        return dis>b.dis;
    }
    node(int nd=0,int dis=0):
        nd(nd),dis(dis){}
};

利用前向星记录最短路

用一个下标为终点点号的数组存边号
用前向星记录起点的点号

while(v!=s)
	v=e[way[v].from;
相关标签: 奇技淫巧