奇技淫巧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.板子基本操作流程
>>>>>>>>>>>>>>>>>>>>>>>>> ...
随机推荐
- Linux内核同步机制之原子操作
1.前言 原子操作指的是该操作不会在执行完毕之前被任何其它任务或事件打断,它是最小的执行单位,不会有比它更小的执行单位,原子实际上使用了物理学中物质微粒的概念,在Linux内核中,原子操作需要硬件的支 ...
- 使用STS加入controller注解后编写程序无法自动提示
1.加入@Controller注解后编写程序无法自动提示,去掉了@Controller注解后就可以了! 2.解决方案:将@Controller替换为@RestController后,可以完美的 ...
- 一步一步的理解javascript的预编译
首先,我们要知道javascript是单线程.解释性语言.所谓解释性语言,就是翻译一句执行一句.而不是通篇编译成一个文件再去执行. 其实这么说还没有这么直观,读一句执行一句那是到最后的事了.到JS执行 ...
- git rebase的使用: 合并多次commit记录; rebase一个分支的起点
合并多次commit记录: good:https://blog.csdn.net/csdlwzy/article/details/83379546 使用 git log 命令查看提交历史: 想要合并前 ...
- 通过IP获取MAC地址例子(内核层)
博客地址:http://home.cnblogs.com/u/zengjianrong/ 在内核处理此流程,反而更加简单些,代码如下: #include <net/arp.h> #incl ...
- 【前端知识体系-CSS相关】CSS基础知识强化
1.CSS样式(选择器)的优先级? 1.1 权重的计算规则 第一优先级:无条件优先的属性只需要在属性后面使用!important.它会覆盖页面内任何位置定义的元素样式.(ie6支持上有些bug). 第 ...
- Java SPI机制:ServiceLoader实现原理及应用剖析
一.背景 SPI,全称Service Provider Interfaces,服务提供接口.是Java提供的一套供第三方实现或扩展使用的技术体系.主要通过解耦服务具体实现以及服务使用,使得程序的可扩展 ...
- 喜大普奔,又拍云全新产品 WebSocket 上线啦
作为一款现象级 MMORPG,魔兽世界迎来了自己的 9.0 版本.巧的是,又拍云最近也更新发布了一款产品--WebSocket.你可能会说,两者有个 mao 关系,不着急.我们先来聊聊魔兽世界~ 熟悉 ...
- c# 对XML进行数字签名并且让java验签成功
实现: 1.c#将xml报文做数字签名发送到java服务,java服务成功验签. 2.c#服务对收到java服务推送的xml报文成功验签. 前提: 1.java服务要求 遇到问题: 1.Java和.n ...
- 微服务架构 ------ DockerCompose从安装到项目部署
DockerCompose的目的:简化Docker的启动和停止流程,以及编排Docker启动服务与服务之间的关系 DockerCompose的安装:curl -L https://get.daoclo ...