奇技淫巧and板子
本文将记录一些奇技淫巧和板子(最基础的也有),先从今天开始写,以前的找个时间再补上
杂项
(2020.4.29之前写的)没有系统的提纲,很杂乱,没什么看点,因此以后的会整理一下
求第\(k\)大的数
应用快速排序思想(\(O(n)\)),平常都是\(O(nlogn)\)
基于快排的思想,在每一层递归中,随机选取一个数做基准时,统计出大于基准值的数的个数\(cnt\),如果\(k<=cnt\)就在左半段(比基准数大)中寻找第\(k\)大的数,反之则在右半段寻找第\(k-cnt\)大的数
复杂度证明:
因为每次只进入了左右两段的任意一个,则在平均情况之下复杂度为:\(n+\frac{n}{2}+\frac{n}{3}+.....+1=O(n)\)
求长度不小于L的子段使之和最大
ST表
预处理
void st_prework() {
for(int i=1; i<=n; ++i) f[i][0]=a[i];
for(int j=1; j<=21; ++j)
for(int i=1; i+(1<<j)-1<=n; ++i)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
查询
int query(int l,int r) {
int res=-9999;
int k=0;
while((1<<(k+1)<=r-l+1)) k++;
res=max(f[l][k],f[r-(1<<k)+1][k]);
return res;
}
\(O(1)\)实现能查询栈中最小元素
开两个栈,a存原始数据,b存历史上每个时刻的最小值
举个例子
a:9 2 1 5 3 0 2 <-
b:9 2 1 1 1 0 0 <-
每次插入元素x时,a插入x,b插入min(top(b),x),弹出时一起弹,询问时输出top(b)
二分
之前用的二分太傻比了,需要考虑的东西太多(可是我没有脑子),学长就教了一个咕咕咕的二分
int l=0,r=1e18;//取个大一点的数
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid)) r=mid-1,ans=mid;
else l=mid+1;
}
cout<<ans;
double l=0,r=1e18;//取个大一点的数
while(r-l<=eps)
{
double mid=(l+r)/2;
if(check(mid)) r=mid,ans=mid;
else l=mid;
}
cout<<ans;
树和图的深度优先遍历和广度优先遍历
//dfs
void dfs(int x)
{
visit[x]=1;
for(int i=head[x];i;i=e[i].Next)
{
int to=e[i].v;
if(visit[to]) continue;
dfs(to);
}
}
//bfs
void bfs()
{
queue<int>q;
q.push(1);
d[1]=1;//层数
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].Next)
{
int to=e[i].v;
if(visit[to]) continue;
d[to]=d[u]+1;
q.push(to);
}
}
}
树的dfs序
dfs序的特点:
每个节点x编号在序列中出现两次,而且以这两次出现位置为端点的闭区间就是以x为根的子树的DFS序
void dfs(int x)
{
a[++len]=x;//记录dfs序
visit[x]=1;
for(int i=head[x];i;i=e[i].Next)
{
int to=e[i].v;
if(visit[to]) continue;
dfs(to);
}
a[++len]=x;
}
求树的重心
void dfs(int x)
{
int max_part=0;//删除掉x后最大子树大小
size[x]=1;//子树x的大小
visit[x]=1;
for(int i=head[x];i;i=e[i].Next)
{
int to=e[i].v;
if(visit[to]) continue;
dfs(to);
size[x]+=size[y];
max_part=max(max_part,size[y]);
}
max_part=max(max_part,n-size[x]);//n为整颗树的节点数目
if(max_part<ans)
{
ans=max_part;//记录重心对应的max_part值
pos=x;//记录重心编号
}
}
图的联通块划分
void dfs(int x)
{
visit[x]=cnt;
for(int i=head[x];i;i=e[i].Next)
{
int to=e[i].v;
if(visit[to]) continue;
dfs(to);
}
}
for(int i=1;i<=n;++i)
if(!visit[i]) cnt++,dfs(i);
拓扑排序
void topsort()
{
queue<int>q;
for(int i=1;i<=n;++i)
if(du[i]==0) q.push(i);//du在add时记录
while(!q.empty())
{
int u=q.front();
q.pop();
a[++len]=u;//记录拓扑序
for(int i=head[u];i;i=e[i].Next)
{
int to=e[i].v;
if(--du[to]==0) q.push(to);
}
}
}
使用负数下表
int * z=y+50
z[50]-->y[0]
treap平衡树
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+2019;
const int INF=(1<<30);
int sum=0,R=0;
int size[N],v[N],num[N],rd[N],son[N][2];
void pushup(int p) {
size[p]=size[son[p][0]]+size[son[p][1]]+num[p];
}
void rotate(int &p,int d) {
int k=son[p][d^1];
son[p][d^1]=son[k][d];
son[k][d]=p;
pushup(p),pushup(k);
p=k;
}
void ins(int &p,int x) {
if(!p) {
p=++sum;
size[p]=num[p]=1;
v[p]=x,rd[p]=rand();
return ;
}
if(v[p]==x) {
num[p]++,size[p]++;
return ;
}
int d=(x>v[p]);
ins(son[p][d],x);
if(rd[p]<rd[son[p][d]]) rotate(p,d^1);
pushup(p);
}
void del(int &p,int x) {
if(!p) return ;
if(x<v[p]) del(son[p][0],x);
else if(x>v[p]) del(son[p][1],x);
else {
if(!son[p][0]&&!son[p][1]) {
num[p]--,size[p]--;
if(num[p]==0) p=0;
} else if(son[p][0]&&!son[p][1]) {
rotate(p,1);
del(son[p][1],x);
} else if(!son[p][0]&&son[p][1]) {
rotate(p,0);
del(son[p][0],x);
} else if(son[p][0]&&son[p][1]) {
int d=(rd[son[p][0]]>rd[son[p][1]]);
rotate(p,d);
del(son[p][d],x);
}
}
pushup(p);
}
int paiming(int p,int x)
{
if(!p) return 0;
if(v[p]==x) return size[son[p][0]]+1;
if(v[p]<x) return size[son[p][0]]+num[p]+paiming(son[p][1],x);
if(v[p]>x) return paiming(son[p][0],x);
}
int find(int p,int x)
{
if(!p) return 0;
if(size[son[p][0]]>=x) return find(son[p][0],x);
else if(size[son[p][0]]+num[p]<x) return find(son[p][1],x-num[p]-size[son[p][0]]);
else return v[p];
}
int pre(int p,int x)
{
if(!p) return -INF;
if(v[p]>=x) return pre(son[p][0],x);
else return max(v[p],pre(son[p][1],x));
}
int Next(int p,int x)
{
if(!p) return INF;
if(v[p]<=x) return Next(son[p][1],x);
else return min(v[p],Next(son[p][0],x));
}
int main() {
int n;
scanf("%d",&n);
for (int i=0; i<n; ++i) {
int opt,x;
scanf("%d%d",&opt,&x);
if (opt==1) ins(R,x);
else if (opt==2) del(R,x);
else if (opt==3) printf("%d\n",paiming(R,x));
else if (opt==4) printf("%d\n",find(R,x));
else if (opt==5) printf("%d\n",pre(R,x));
else if (opt==6) printf("%d\n",Next(R,x));
}
return 0;
}
fhq treap
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+2019;
struct node {
int l,r;
int val,key;
int size;
} fhq[N];
int T;
int cnt,root;
int nownode(int val) {
fhq[++cnt].val=val;
fhq[cnt].size=1;
fhq[cnt].key=rand();
return cnt;
}
void update(int p) {
fhq[p].size=fhq[fhq[p].l].size+fhq[fhq[p].r].size+1;
}
void spilt(int now,int val,int &x,int &y) {//x和y是拆分后两树的根节点
if(!now) x=y=0;
else {
if(fhq[now].val<=val) {
x=now;
spilt(fhq[now].r,val,fhq[now].r,y);//拆分右子树,因为右子树中可能还存在比val小的节点
} else {
y=now;
spilt(fhq[now].l,val,x,fhq[now].l);//复读机
}
update(now);
}
}
int merge(int x,int y) {
if(!x||!y) return x+y;
if(fhq[x].key>fhq[y].key) { //维护根的性质
//根据堆的性质得到的新树x在y上面,而且根据二叉搜索树的性质y一定在x下面,所有y在x右下
fhq[x].r=merge(fhq[x].r,y);
update(x);
return x;
} else { //复读机
fhq[y].l=merge(x,fhq[y].l);
update(y);
return y;
}
}
int x,y,z;
void ins(int val) {
spilt(root,val,x,y);
root=merge(merge(x,nownode(val)),y);//这里忘给root负值了
}
void del(int val) {
spilt(root,val,x,z);
spilt(x,val-1,x,y);
y=merge(fhq[y].l,fhq[y].r);
root=merge(merge(x,y),z);
}
int getrank(int val) {
spilt(root,val-1,x,y);
int ret=fhq[x].size+1;
root=merge(x,y);//先return再合并
return ret;
}
int getnum(int pm) {
int now=root;
while(now) {
if(fhq[fhq[now].l].size+1==pm) break;
else if(fhq[fhq[now].l].size>=pm) now=fhq[now].l;
else {
pm-=fhq[fhq[now].l].size+1;
now=fhq[now].r;
}
}
return fhq[now].val;
}
int pre(int val) {
spilt(root,val-1,x,y);
int now=x;
while(fhq[now].r) now=fhq[now].r;
int ret=fhq[now].val;
root=merge(x,y);
return ret;
}
int Next(int val) {
spilt(root,val,x,y);
int now=y;
while(fhq[now].l) now=fhq[now].l;
int ret=fhq[now].val;
root=merge(x,y);
return ret;
}
int main() {
srand((unsigned)time(0));
scanf("%d",&T);
while(T--) {
int opt,x;
scanf("%d%d",&opt,&x);
if(opt==1) ins(x);
if(opt==2) del(x);
if(opt==3) cout<<getrank(x)<<'\n';
if(opt==4) cout<<getnum(x)<<'\n';
if(opt==5) cout<<pre(x)<<'\n';
if(opt==6) cout<<Next(x)<<'\n';
}
return 0;
}
可能是splay
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+2019;
const int INF=(1<<30);
int sum=0,R=0;
int size[N],v[N],num[N],rd[N],son[N][2];
void pushup(int p) {
size[p]=size[son[p][0]]+size[son[p][1]]+num[p];
}
void rotate(int &p,int d) {
int k=son[p][d^1];
son[p][d^1]=son[k][d];
son[k][d]=p;
pushup(p),pushup(k);
p=k;
}
void ins(int &p,int x) {
if(!p) {
p=++sum;
size[p]=num[p]=1;
v[p]=x,rd[p]=rand();
return ;
}
if(v[p]==x) {
num[p]++,size[p]++;
return ;
}
int d=(x>v[p]);
ins(son[p][d],x);
if(rd[p]<rd[son[p][d]]) rotate(p,d^1);
pushup(p);
}
void del(int &p,int x) {
if(!p) return ;
if(x<v[p]) del(son[p][0],x);
else if(x>v[p]) del(son[p][1],x);
else {
if(!son[p][0]&&!son[p][1]) {
num[p]--,size[p]--;
if(num[p]==0) p=0;
} else if(son[p][0]&&!son[p][1]) {
rotate(p,1);
del(son[p][1],x);
} else if(!son[p][0]&&son[p][1]) {
rotate(p,0);
del(son[p][0],x);
} else if(son[p][0]&&son[p][1]) {
int d=(rd[son[p][0]]>rd[son[p][1]]);
rotate(p,d);
del(son[p][d],x);
}
}
pushup(p);
}
int paiming(int p,int x)
{
if(!p) return 0;
if(v[p]==x) return size[son[p][0]]+1;
if(v[p]<x) return size[son[p][0]]+num[p]+paiming(son[p][1],x);
if(v[p]>x) return paiming(son[p][0],x);
}
int find(int p,int x)
{
if(!p) return 0;
if(size[son[p][0]]>=x) return find(son[p][0],x);
else if(size[son[p][0]]+num[p]<x) return find(son[p][1],x-num[p]-size[son[p][0]]);
else return v[p];
}
int pre(int p,int x)
{
if(!p) return -INF;
if(v[p]>=x) return pre(son[p][0],x);
else return max(v[p],pre(son[p][1],x));
}
int Next(int p,int x)
{
if(!p) return INF;
if(v[p]<=x) return Next(son[p][1],x);
else return min(v[p],Next(son[p][0],x));
}
int main() {
int n;
scanf("%d",&n);
for (int i=0; i<n; ++i) {
int opt,x;
scanf("%d%d",&opt,&x);
if (opt==1) ins(R,x);
else if (opt==2) del(R,x);
else if (opt==3) printf("%d\n",paiming(R,x));
else if (opt==4) printf("%d\n",find(R,x));
else if (opt==5) printf("%d\n",pre(R,x));
else if (opt==6) printf("%d\n",Next(R,x));
}
return 0;
}
位运算
补码
\(c\)按位取反后结果为\(-1-c\)
一个小技巧
\]
奇技淫巧and板子的更多相关文章
- C#开发奇技淫巧三:把dll放在不同的目录让你的程序更整洁
系列文章 C#开发奇技淫巧一:调试windows系统服务 C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件 C#开发奇技淫巧三:把dll放在不同的目录让你的程序更整洁 程序目录的整理 ...
- [板子]最小费用最大流(Dijkstra增广)
最小费用最大流板子,没有压行.利用重标号让边权非负,用Dijkstra进行增广,在理论和实际上都比SPFA增广快得多.教程略去.转载请随意. #include <cstdio> #incl ...
- [板子]ISAP
ISAP求最大流,敲了一发板子,无压行,教程略去.转载请随意. #include <cstdio> #include <cstring> #include <algori ...
- [板子]倍增LCA
倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...
- UP Board 人若有大胆,板子就很惨:首次上电开机失败
前言 原创文章,转载引用务必注明链接. 注意:拍照自带抖动功能,画质大家凑合着看.冬日天气干燥,手触摸板子前建议流水洗手或者握持大体积导电体将静电放走. 本文使用Markdown写成,为获得更好的阅读 ...
- orpsocv2 从ROM(bootrom)启动分析--以atlys板子的启动为例子
1 复位后的启动地址 1) 复位后,启动地址在or1200_defines.v最后宏定义,atlys板子的目录:orpsocv2\boards\xilinx\atlys\rtl\verilog\inc ...
- 【CSS进阶】box-shadow 与 filter:drop-shadow 详解及奇技淫巧
box-shadow 在前端的 CSS 编写工作想必十分常见.但是 box-shadow 除去它的常规用法,其实还存在许多不为人知的奇技淫巧. 喜欢 markdown 版本的可以戳这里. box-sh ...
- Lattice FPGA 板子 调试笔记
最近在调试LATTICE FPGA 做的视频板子,颇不顺利,所以记录下来作为以后的参考: 1.FPGA的IO口不是所有的都是双向的,有些有特殊作用的是单向的. 在查阅 LatticeECP3-17E ...
- 【图像处理】【SEED-VPM】1.板子基本操作流程
>>>>>>>>>>>>>>>>>>>>>>>>> ...
随机推荐
- 【排错】springboot项目,启动报An attempt was made to call the method com.google.gson.GsonBuilder.setLenient()Lcom/google/gson/GsonBuilder; but it does not exist.
pom文件新引入: <dependency> <groupId>com.google.code.gson</groupId> ...
- fiverr无法注册的解决办法,fiverr注册教程
转载 https://www.wok99.com/450.html
- 不依赖Spring使用AspectJ达到AOP面向切面编程
网上大多数介绍AspectJ的文章都是和Spring容器混用的,但有时我们想自己写框架就需要抛开Spring造轮子,类似使用原生AspectJ达到面向切面编程.步骤很简单,只需要两步. 1.导入依赖 ...
- notepad++格式化代码,自动对齐
Notepad++本身没有快捷命令格式化JavaScript代码,需要通过安装扩展插件来实现快捷格式化JS代码的功能.本文主要介绍如何通过安装JStool插件来实现格式化JS代码的功能. 在插件列表中 ...
- 为什么改了JS数组中的一个元素的值,其他数组元素值都跟着变了
原因: 数组是引用类型,数组变量存储在栈,元素数据存储在堆中,将数组赋值不同的对象,所以的赋值对象都指向堆同一个数据,所以改变其中一个数组中的元素,别的数组元素也会改变. 解决方案: 原理就是先把数组 ...
- 兼容 .NET Core3.0, Natasha 框架实现 隔离域与热编译操作
关于 Natasha 动态构建已经成为了封装者们的家常便饭,从现有的开发趋势来看,普通反射性能之低,会迫使开发者转向EMIT/表达式树等构建方式,但是无论是EMIT还是表达式树,都会依赖于反射的 ...
- 程序游戏推荐(C语言贪吃蛇,python天天酷跑(需要安装pygame),js是狠人就坚持30s)
下面是下载位置,我把他们上传到我的文件下了. C语言贪吃蛇:https://files.cnblogs.com/files/ITXiaoAng/%E8%B4%AA%E5%90%83%E8%9B%87. ...
- spring AOP的两种配置
xml配置 定义要被代理的方法的接口 public interface TestAop { public void print(String s); } 实现上述接口 public class Tes ...
- html书写行内元素时-tab和换行会在行内元素间引入间距
目录 html文本中的控制字符会被解析为文本节点 书写行内元素时,换行符LF与水平制表符HT会引入莫名的元素间间隔 其他控制字符是否会引入间距的验证 html文本中的控制字符会被解析为文本节点 举例: ...
- c# 开发+MySql数据库
今天就一个客户端的任务:1.把Excel文件转成特定格式插入到数据库中:2.查出该文件,并且导出Excel文件:3.如果插入数据错误,则把刚插入的数据删除掉.感觉比较简单,可是,墨迹了一天呀....总 ...