首页 > 其他分享 >散知识点总结(持更)

散知识点总结(持更)

时间:2024-08-10 23:27:16浏览次数:10  
标签:总结 知识点 ch 树状 int sum 数组 dis

有一些小 trick,专门用一整篇博客来写不太合适,所以都放在这里吧。

逆序对

考试的时候树状数组做法显然比其他的都好写。

考虑每个元素对答案的贡献,我们需要知道在它之前有多少元素比它大。

我们只需要维护一个权值树状数组,在枚举到 \(i\) 的时候查询当前树状数组中的元素有多少比它大,为了方便处理我们倒序枚举,这样相当于求顺序对,方便树状数组计算答案。

每次累加以后只需要把当前元素加进树状数组即可。

for(int i=n;i>=1;i--) 
{
	ans+=ask(a[i]-1);	
	add(a[i],1);
}

二进制分组

如果我们有一堆数字,现在要把它们多次分成两组,要求对于每两个数字都至少有一次分在不同的组。

我们考虑二进制,对于每一位,把所有数字这一位为 \(0\) 的分成一组,为 \(1\) 的分成一组,可以证明这样一定能满足上述条件。

简单证明

对于两个不同的数字 \(i,j\),它们的二进制表达一定至少有一位是不同的,。因此按照上述分组方法一定会至少有一次不在同一组里面。

证毕。

分组的过程很简单,所以给一道例题。

[GXOI/GZOI2019] 旅行者

把所有感兴趣的城市进行二进制分组,然后搞两个虚拟点,一个起点一个终点,分别给两组点连 \(0\) 边权的边,然后跑最短路即可。

可爱的代码
#include<bits/stdc++.h>
#define int long long
inline int read()
{
	int w=1,s=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
	return w*s;
} 
using namespace std;
const int maxn=1e6+10;
int T,n,m,k;
int a[maxn];
struct no
{
	int y,v;
};
vector<no> G[maxn];
struct dij
{
	int y,id;
	inline friend bool operator < (dij x,dij y)
	{
		return x.y>y.y;
	}
};
int dis[maxn];
bool vis[maxn];
void dijkstra()
{
	memset(dis,0x3f,sizeof dis);
	memset(vis,0,sizeof vis);
	priority_queue<dij> q;
	dis[0]=0;
	q.push({0,0});
	while(!q.empty())
	{
		int u=q.top().id;
		q.pop();
		if(vis[u])continue;
		vis[u]=1;
		for(auto i : G[u])
		{
			int y=i.y,v=i.v;
			if(dis[u]+v<dis[y])
			{
				dis[y]=dis[u]+v;
				if(!vis[y])
				q.push({dis[y],y});
			}
		}
	}
}
signed main()
{
//	freopen("tourist.in","r",stdin);
//	freopen("tourist.out","w",stdout);
	cin>>T;
	while(T--)
	{
		n=read(),m=read(),k=read();
		for(int i=0;i<=n;i++)G[i].clear();
		for(int i=1;i<=m;i++)
		{
			int x=read(),y=read(),v=read();
			G[x].push_back({y,v});
		}
		for(int i=1;i<=k;i++)a[i]=read();
		int ans=0x3f3f3f3f3f3f;
		for(int i=0;(1<<i)<=n;i++)
		{
			G[0].clear();
			for(int j=1;j<=k;j++)
			{
	            if(a[j]&(1<<i))G[0].push_back({a[j],0});
	            else G[a[j]].push_back({n+1,0});
        	}
        	dijkstra();
        	ans=min(ans,dis[n+1]);
        	for(int j=1;j<=k;j++)
            if((!(a[j]&(1<<i))))G[a[j]].pop_back();
	        G[0].clear();
	        for(int j=1;j<=k;j++)
			{
	            if(!(a[j]&(1<<i)))G[0].push_back({a[j],0});
	            else G[a[j]].push_back({n+1,0});
	    	}
	        dijkstra();
	        ans=min(ans,dis[n+1]);
	        for(int j=1;j<=k;j++)
	        if((a[j]&(1<<i))) G[a[j]].pop_back();      
		}
		printf("%lld\n",ans);
	}
	return 0;
}

其实简单一想就能发现类似的还有三进制四进制之类的分组,不过这些也不常用,但知道一点是一点。

高维前缀和

这个不是树状数组区间操作的高维前缀和(这个谁用啊),而是维度。

类比ABC366D这道题,先给出一到三维前缀和数组的计算方法:

\[sum_i=a_i+sum_{i-1} \]

\[sum_{i,j}=a_{i,j}+sum_{i-1,j}+sum_{i,j-1}-sum_{i-1,j-1} \]

\[sum_{i,j,k}=a_{i,j,k}+sum_{i,j,k-1}+sum_{i,j-1,k}+sum_{i-1,j,k}-sum_{i,j-1,k-1}-sum_{i-1,j,k-1}-sum_{i-1,j-1,k}+sum_{i-1,j-1,k-1} \]

代码版(复制用)
sum[i]=a[i]+sum[i-1];
sum[i][j]=a[i][j]+sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1];
sum[i][j][k]=a[i][j][k]+sum[i][j][k-1]+sum[i][j-1][k]+sum[i-1][j][k]-sum[i][j-1][k-1]-sum[i-1][j][k-1]-sum[i-1][j-1][k]+sum[i-1][j-1][k-1];

稍微懂一点数学的人都已经能看出来规律了。进行 \(n\) 维前缀和的时候,对于前缀和数组的每一维,我们分别对 \(1\sim n\) 个下标进行 \(-1\) 的修改,如果修改个数维奇数,则符号为加号,否则为减号。

容易发现若修改个数为 \(m\),则共需要修改 \(n\choose m\) 次。因此太高维的一般也不常用,了解即可。

标签:总结,知识点,ch,树状,int,sum,数组,dis
From: https://www.cnblogs.com/Lydic/p/18352951

相关文章

  • 堆总结(C语言)
    堆总结(C语言)二叉树的顺序结构及实现堆是什么堆的分类堆的实现堆的向下调整堆的向上调整堆的应用堆排序TOP-K问题思路:堆是什么堆总是一棵完全二叉树,堆是用来存完全二叉树的,如果存普通的二叉树就会浪费空间。堆(一种二叉树)使用顺序结构的数组来存储。堆不是简单的......
  • 第六周总结
    本周,我专注于科目三的驾驶练习,逐渐熟悉了道路行驶的各种操作要求,包括起步、换挡、加减速、变道等实际驾驶技能。在反复的练习中,我对车辆的操控感更加得心应手,为即将到来的考试奠定了基础。除此之外,我还深入了解了Spark在大数据领域中的重要作用。Spark是一种快速、通用、可扩展的......
  • 快速多项式全家桶 简略总结 (不确定里面的内容对不对)
    多项式牛顿迭代解决的问题:求一个[多项式函数](?)\(G\),使得\(F(G)\equiv0\pmod{x^n}\)。(听XK提到泛函分析)\[G_{k+1}\equivG_k-\frac{F(G_k)}{F'(G_k)}\pmod{x^{2^{k+1}}}\]求导时把\(G\)当成未知数,不要对\(G\)求导。倍增。加法每一项对应......
  • CUDA--内存访问越界或无效的索引操作解决办法--总结
    设备端的断言错误(device-sideasserttriggered)通常发生在CUDA代码中访问无效的内存地址或执行了无效的操作。解决这种错误需要系统地排查代码中的潜在问题。以下是详细的解决方案:1.检查数组边界确保所有访问数组或指针的操作都在有效范围内。检查线程索引和块索引的计算,确......
  • 每周总结
    本周在学习Hadoop的过程中,我深入了解了分布式文件系统(HDFS)的原理和操作,并开始接触和使用MapReduce框架进行数据处理和分析。以下是我这周的学习和实践总结:理论学习与实践应用在分布式文件系统(HDFS)的学习中,我掌握了其设计理念、架构和工作原理。HDFS通过将大文件分割成多个块,并将......
  • 第五周总结
    本周我进一步探索了Hadoop生态系统中的其他工具和技术。除了核心的HDFS和MapReduce之外,我还学习了Hive、Pig和Spark等工具。Hive提供了SQL-like查询语言HiveQL,使用户能够轻松进行数据提取、转换和加载(ETL)。Pig则提供了一种脚本语言PigLatin,用于数据流的处理和分析。Spark作为一种......
  • 初中数学知识点(不含几何)
    文章目录一、整式1.同底数幂的乘法2.幂的乘方3.积的乘方4.乘法分配律5.同底数幂的除法二、分式1.分式的乘法2.分式的除法3.分式的乘方4.分式的最简公分母5.负指数幂6.比例变形7.分离常数法三、二次根式0.平方根和算数平方根的重要概念1.乘方去根号2.二......
  • 第四周周报总结
    本周在准备rk,打了几场训练赛然后自己打了几场rk模拟赛,感觉手感还可以然后还打了牛客一场,这道题挺值得补的题解:2022RoboCom世界机器人开发者大赛-本科组(省赛)-whatdo+-博客园(cnblogs.com)2021RoboCom世界机器人开发者大赛-本科组(决赛)-whatdo+-博客园(cnblogs.c......
  • Java知识点1
    Java知识点什么是字节码?采用字节码的好处是什么?在Java中,JVM可以理解的代码就叫做字节码(即扩展名为.class的文件),它只面向虚拟机。Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。字节码并不针对一种特定......
  • P9750 [CSP-J 2023] 一元二次方程题目总结
    根据题面,我们将分为多种情况讨论:若a为负数,那么将a,b,c全部取反首先求出data=b^2-4*a*c;1,data<=0cout<<”NO”;否则带入求跟公式:-b/2a+(-)sqrt(data)注意::gcd(a,b)有可能为负数,此处应用abs(x)取绝对值若开根号data为有理数{-b为2*a的倍数则直接输出b否则输出b/gcd(b,2*a......