这里记录了平时个人常用的一些不好分类的代码模板。
杂项 常用宏定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #pragma GCC optimize(2) #pragma G++ optimize("O2" ) #pragma comment(linker, "/STACK:102400000,102400000" ) #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <iomanip> #include <string> using namespace std;typedef long long ll;const int inf=0x3f3f3f3f ;const int maxn=200005 ;#define PI 3.14159265358979323846 #define e 2.7182818284590452354 #define ln_2 0.69314718055994530942 #define ln_10 2.30258509299404568402 int main () { std::ios::sync_with_stdio (false ),cin.tie (0 ),cout.tie (0 ); #ifdef DEBUG freopen ("input.txt" , "r" , stdin); #endif return 0 ; }
cb 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <bits/stdc++.h> using namespace std;typedef long long ll;typedef pair<int ,int >pii;#define ff first #define ss second #define debug(x) std:: cerr << #x << " = " << x << std::endl; const int maxn=2e5 +10 |,inf=0x3f3f3f3f ,mod=1000000007 ;const ll INF=0x3f3f3f3f3f3f3f3f ;const double eps=1e-9 ;void read () {}template <typename T,typename ... T2>inline void read (T &x,T2 &... oth) { x=0 ; int ch=getchar (),f=0 ; while (ch<'0' ||ch>'9' ){if (ch=='-' ) f=1 ;ch=getchar ();} while (ch>='0' &&ch<='9' ){x=(x<<1 )+(x<<3 )+(ch^48 );ch=getchar ();} if (f)x=-x; read (oth...); } signed main (signed argc, char const *argv[]) { std::ios::sync_with_stdio (false ),cin.tie (0 ),cout.tie (0 ); #ifdef DEBUG freopen ("input.in" , "r" , stdin); #endif return 0 ; }
快速读入 1 2 3 4 5 6 7 8 void read () {}template <typename T,typename ... T2>inline void read (T &x,T2 &... oth) { x=0 ; int ch=getchar (),f=0 ; while (ch<'0' ||ch>'9' ){if (ch=='-' ) f=1 ;ch=getchar ();} while (ch>='0' &&ch<='9' ){x=(x<<1 )+(x<<3 )+(ch^48 );ch=getchar ();} if (f)x=-x; read (oth...); }
CDQ分治 使用分治+双指针,用于处理偏序计数问题。
CF641E Little Artem and Time Machine 你有一个初始为空的可重集,按给定顺序 进行如下$q$次操作:
在时间$t$时刻插入一个$x$.
在时间$t$时刻删除一个$x$.
询问在$t$时刻有多少个$x$(只考虑本次操作之前操作所造成的影响).
思路 操作本身有偏序关系,此前的操作的各个时间点$t$也有偏序关系。
cdq分治下去,将操作分为左右两块,分别按时间点$t$来排序,用双指针分别指向左区间和右区间,来统计左区间的操作对于右区间所有点的影响。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 struct opt { int id,op,t,x; opt (int a=0 ,int b=0 ,int c=0 ,int d=0 ): id (a),op (b),t (c),x (d){} bool operator < (const opt &y)const { return t>y.t; } } a[maxn]; vector<bool >ok; vector<int >ans,mp,v1; void cdq (int l,int r) { if (l==r) return ; int mid=(l+r)>>1 ; cdq (l,mid); cdq (mid+1 ,r); sort (a+l,a+mid+1 ); sort (a+mid+1 ,a+r+1 ); int i=mid+1 ,j=l; for (;i<=r;i++) { for (;a[j].t<=a[i].t&&j<=mid;j++) { if (a[j].op==1 ) mp[a[j].x]++; else if (a[j].op==2 ) mp[a[j].x]--; } if (a[i].op==3 ) ans[a[i].id]+=mp[a[i].x]; } for (j--;j>=l;j--) if (a[j].op!=3 ) mp[a[j].x]+=(a[j].op==1 ?-1 :1 ); } signed main (signed argc, char const *argv[]) { int q,op,t,x; cin>>q; ans.resize (q+1 ,0 ); mp.resize (q+1 ,0 ); ok.resize (q+1 ,0 ); for (int i=1 ;i<=q;i++) { cin>>op>>t>>x; a[i]=opt (i,op,t,x); if (op==3 ) ok[i]=1 ; v1.push_back (x); } sort (v1.begin (),v1.end ()); v1.erase (unique (v1.begin (),v1.end ()),v1.end ()); for (auto &i:a) i.x=lower_bound (v1.begin (),v1.end (),i.x)-v1.begin ()+1 ; cdq (1 ,q); for (int i=1 ;i<=q;i++) if (ok[i]) cout<<ans[i]<<endl; return 0 ; }
整体二分 整体二分算法完整总结
WQS二分 模型 题型1:在物品集合中恰好选取$m$个物品,不同组合情况有不同的价值,要求最大/最小化总价值。
设选取$x$个物品时的最大价值为$g(x)$,以$x$为横坐标,$g(x)$为纵坐标,那么会在坐标系上呈现出一个上凸包的形状(斜率单调递减),即满足$g(i)-g(i-1)\ge g(i+1)-g(i)$,最大差值即作为斜率上下界,即每多选择一个物品额外产生的收益 都是单调递减的。
此时我们不知道$g(x)$的值是多少,使用直线$g(x)=kx+b$来切这个凸包(相当于对每个物品附加了权值$-k$),通过$O(n)$的方法来找到最大的$b$,同时我们也得到了此时的$x$,通过$x$与$m$的关系来调整斜率$k$继续二分使得$x$接近$m$,二分的方向与上凸包还是下凸包有关。
最终$ans=b-mk$,注意当有多个点权值相同时(既有连续几个点的斜率相同,截距相同),要使用$ans=b-mk$而不是$ans=b-xk$,来得到正确答案,注意二分的方向和斜率上限的估计 。
扩展:求限制数量不超过m的最优解 题型2:在所给物品中选取数量没有限制,求出达到最大的收益需要选择的物品数量以及最大收益。
此类题型可以视为无限制问题+wqs二分的一个组合。
我们知道,对于无限制问题可以通过$O(n)$的手段解决,那么如果函数图形是一个上凸包的话,最大值可以轻松得出,如果这个最大值$g(x)$对应的$x\le m$的话,那么就是我们所需要的答案;否则若$x$超出了$m$的限制,那么我们可以将$[1,m]$视为上凸包的左半部分,函数单调递增,斜率单调递减,可以通过$wqs$二分来确定$g(m)$的值即为我们所需要的答案。
学习笔记 关于WQS二分算法以及其一个细节证明
WQS二分 ,可以视为下凸壳的左半部分
习题 坐标轴上有$n$个村庄,要选择$m$个村庄建造邮局,不方便值为每个村庄与其最近的邮局之间的距离总和,你要使其最小。
设$g(x)$为修建邮局的最小不方便值,因为造的地铁站越多$g(x)$越小,所以本题是一个下凸包的左半部分。
使用wqs二分来将问题转化为建造一个邮局花费$-k$代价,使不方便值$-k\times $邮局数最小。
可以发现邮局建立在中点总是最优的,令$mid=\dfrac{l+r}{2}$,这里建造一个邮局控制$[l,r]$区间的贡献为$\sum\limits_{i=l}^{mid}(p_{mid}-p_i)+\sum\limits_{i=mid+1}^{r}(p_{i}-p_{mid})$.
整体复杂度$O(n^2logV)$,单调栈+二分优化dp过程似乎可以$O(nlognlogV)$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 int p[maxn],sum[maxn],dp[maxn],cnt[maxn];pii check (int n,int k) { auto w = [](int l,int r) { int mid=(l+r)>>1 ; return sum[r]+sum[l-1 ]-2 *sum[mid]+(2 *mid-l-r+1 )*p[mid]; }; for (int i=1 ;i<=n;i++) { for (int j=1 ;j<=i;j++) { if (dp[j-1 ]+w (j,i)-k<dp[i]) { dp[i]=dp[j-1 ]+w (j,i)-k; cnt[i]=cnt[j-1 ]+1 ; } } } return make_pair (dp[n],cnt[n]); } signed main (signed argc, char const *argv[]) { int n,m; read (n,m); for (int i=1 ;i<=n;i++) { read (p[i]); sum[i]=sum[i-1 ]+p[i]; } int l=-m*p[n]-10 ,r=10 ,ans=INF; while (l<=r) { int k=(l+r)>>1 ; for (int i=1 ;i<=n;i++) dp[i]=inf,cnt[i]=0 ; pii now=check (n,k); if (now.ss<=m) ans=now.ff+m*k,l=k+1 ; else r=k-1 ; } printf ("%d\n" ,ans); return 0 ; }
本题是一个下凸包(凹函数),每一个状态的最优解可以通过kruskal求得。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 struct edge { int u,v,w,c; edge (){} edge (int u,int v,int w,int c): u (u),v (v),w (w),c (c){} bool operator <(const edge &y) { if (w!=y.w) return w<y.w; return c<y.c; } }; vector<edge>B,W; int fa[maxn],cnt=0 ;int findfa (int x) { if (fa[x]!=x) fa[x]=findfa (fa[x]); return fa[x]; } bool Merge (int x,int y) { int a=findfa (x),b=findfa (y); if (a==b) return 0 ; if (a<b) fa[b]=a; else fa[a]=b; return 1 ; } int kruskal (int n,int k) { for (int i=1 ;i<=n;i++) fa[i]=i; int ans=0 ; vector<edge>E; E.insert (E.end (),W.begin (),W.end ()); for (auto &x:E) x.w-=k; E.insert (E.end (),B.begin (),B.end ()); sort (E.begin (),E.end ()); for (auto &e:E) { if (Merge (e.u,e.v)) { ans+=e.w; n--; if (e.c==0 ) cnt++; if (n==1 ) return ans; } } return ans; } signed main (signed argc, char const *argv[]) { int n,m,need,u,v,c,w; cin>>n>>m>>need; for (int i=1 ;i<=m;i++) { cin>>u>>v>>w>>c; u++,v++; if (c==0 ) W.push_back (edge (u,v,w,c)); else B.push_back (edge (u,v,w,c)); } sort (W.begin (),W.end ()); sort (B.begin (),B.end ()); int l=-105 ,r=105 ,ans=-1 ,b,k; while (l<=r) { k=(l+r)>>1 ; cnt=0 ; b=kruskal (n,k); if (cnt<need) l=k+1 ; else { r=k-1 ; ans=b+k*need; } } cout<<ans<<endl; return 0 ; }
离散化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 struct node { int v,id; bool operator < (const node a)const { return v<a.v; } } a[maxn]; void discretization (int n) { for (int i=1 ;i<=n;i++) a[i].id=i; sort (a+1 ,a+n+1 ); for (int i=1 ;i<=n;i++) rak[a[i].id]=i; }
法2:排序后unique去重确定范围,再用lower_bound
1 2 3 4 5 6 7 8 9 10 ll a[maxn],t[maxn]; void discretization (int n) { for (int i=1 ;i<=n;i++) t[i]=a[i]; sort (t+1 ,t+n+1 ); int m=unique (t+1 ,t+n+1 )-t-1 ; for (int i=1 ;i<=n;i++) a[i]=lower_bound (t+1 ,t+m+1 ,a[i])-t; }
曼哈顿距离与切比雪夫距离 切比雪夫距离定义为两个向量在任意坐标维度上的最大差值。
将原坐标系每个点的坐标$(x,y)$变为$(x+y,x−y)$,则原坐标系中的曼哈顿距离等于新坐标系中的切比雪夫距离。
反过来,将原坐标系每个点的坐标$(x,y)$变为$(\frac{x+y}{2},\frac{x-y}{2})$,则原坐标系中的切比雪夫距离等于新坐标系中的曼哈顿距离。
位运算 GCC内置函数 1 2 3 4 5 int __builtin_popcount(unsigned int x) :返回x的二进制中1 的个数。int __builtin_ffs(int x) :返回x的二进制末尾最后一个1 的位置,位置的编号从1 开始(最低位编号为1 )。当x为0 时返回0 。int __builtin_clz(unsigned int x) :返回x的二进制的前导0 的个数。当x为0 时,结果未定义。int __builtin_ctz(unsigned int x) :返回x的二进制末尾连续0 的个数。当x为0 时,结果未定义。
判断是否为2的幂 1 bool isPowerOfTwo (int n) { return n > 0 && (n & (n - 1 )) == 0 ; }
判断两个数符号位是否相同 1 bool isSameSign (int x, int y) { return (x ^ y) >= 0 ; }
一些不好分类的算法 判断闰年 1 2 3 4 5 6 bool Isleap (int year) { if (year%400 ==0 ||year%100 &&year%4 ==0 ) return true ; return false ; }
求日期差 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int leap (int y) { if (!y) return 0 ; return y/4 -y/100 +y/400 ; } int calc (int day,int mon,int year) { int res=(year-1 )*day+leap (year-1 ); int s[12 ]={31 ,28 ,31 ,30 ,31 ,30 ,31 ,31 ,30 ,31 ,30 ,31 }; for (int i=1 ;i<mon;i++) res+=s[i]; if (Isleap (year)&&mon>2 ) res++; res+=day; return res; } ll count_day (int da,int ma,int ya,int db,int mb,int yb) { int resa=calc (da,ma,ya); int resb=calc (db,mb,yb); return abs (resa-resb); }
蔡勒公式 给定日期求星期几,返回0~6,要加一。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int whatday (int day,int mon,int year) { int ans; if (mon==1 ||mon==2 ) { mon+=12 ; year--; } if ((year<1752 )||(year==1752 &&mon<9 )||(year==1752 &&mon==9 &&day<3 )) ans=(day+2 *mon+3 *(mon+1 )/5 +year+year/4 +5 )%7 ; else ans=(day+2 *mon+3 *(mon+1 )/5 +year+year/4 -year/100 +year/400 )%7 ; return ans; }
模拟退火 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #include <bits/stdc++.h> using namespace std;const double delta=0.996 ;int n;double sx,sy;double ansx,ansy;double ans=1e18 +10 ,temper;struct node { double x,y,w; } a[1005 ]; int read () { int x=0 ,f=1 ; char ss=getchar (); while (ss<'0' ||ss>'9' ){if (ss=='-' )f=-1 ;ss=getchar ();} while (ss>='0' &&ss<='9' ){x=x*10 +ss-'0' ;ss=getchar ();} return x*f; } inline double evaluate (const double &x,const double &y) { double ret=0 ; for (register int i=1 ;i<=n;i++) { double dx=x-a[i].x,dy=y-a[i].y; ret+=(double )sqrt (dx*dx+dy*dy)*a[i].w; } return ret; } void simulateAnneal () { double nowx=ansx,nowy=ansy; ans=evaluate (nowx,nowy); for (temper=2e3 +50 ;temper>1e-14 ;temper*=delta) { double nexx=nowx+temper*(((rand ()<<1 )-RAND_MAX)); double nexy=nowy+temper*(((rand ()<<1 )-RAND_MAX)); double now=evaluate (nexx,nexy); double diss=now-ans; if (diss<=0 ) { nowx=nexx,nowy=nexy; ansx=nowx,ansy=nowy; ans=now; } else if (exp (-diss/temper)*RAND_MAX>rand ()) { nowx=nexx,nowy=nexy; } } } void ac (int ca) { for (int i=1 ;i<=n;i++) sx+=a[i].x,sy+=a[i].y; ansx=sx/n,ansy=sy/n; for (register int i=1 ;i<=ca;i++) { srand (rand ()); simulateAnneal (); } } int main () { srand (time (0 )); srand (rand ()); scanf ("%d" ,&n); for (int i=1 ;i<=n;i++) { scanf ("%lf%lf%lf" ,&a[i].x,&a[i].y,&a[i].w); } ac (15 ); printf ("%.3lf %.3lf\n" ,ansx,ansy); return 0 ; }
CB简易使用手册
操作
快捷键
显示信息栏
F2
显示管理栏
Shift + F2
跳转指定行
Ctrl + G
跳转至下一未保存修改行
Ctrl + F3 / Ctrl + Shift + F3
开启自动换行
Settings->Editor->Other Options->Word warp
开启自动完成
Settings->Editors->Code completion
重复上一次操作
Ctrl + Shift + Z
与上一行调换
Ctrl + T
添加书签
Ctrl + B
跳转书签
Alt + PgUp / PgDown
跳转上下函数
Ctrl + PgUp / PgDown
呼出最近打开的文件
Ctrl + Tab
向上/下滚动
Ctrl + Up / Down
跳转一个单词
Ctrl + Left / Right
豆沙绿配色 Settings>Editor>Syntax Highlighting
调整背景色
在Settings->Editor->左侧General settings,修改字体为Consolas,字号选择11号,同时把下面的show line numbers选中
调整字体
色调:85。饱和度:123。亮度:205.
鹅黄:241,229,201.
如何调试 新建项目:File -> New -> Project... -> Console application -> Go -> 填写项目名和路径 -> 选择默认编译器 -> 在main中编写C++
启动调试器:View -> Toolbars -> Debugger
呼出调试栏,以Debug模式启动,点击按钮debug,打开调试窗口Watches可以显示变量值。点击 Next line 执行下一个语句,右边的Step into为执行内部语句,最右侧的红色按钮Stop debugger为结束调试;当执行到函数调用时,可以使用next line直接执行函数,或step into跳转到函数内部执行语句,希望停止调试则点击stop debugger。
Function
Shortcut Key
Debug
F8
Continue debugging
Ctrl + F7
跳过代码块
F7
单步执行代码块
Shift + F7
跳出代码块
Ctrl + Shift + F7
切换断点
F5
运行到光标
F4
Previous error
Alt + F1
Next error
Alt + F2
gvim简易手册 _vimrc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 set nocompatiblesource $VIMRUNTIME /vimrc_example.vim source $VIMRUNTIME /mswin.vim behave mswin set encoding =utf-8 fileencodings =utf-8 termencoding =utf-8 "自动识别utf8 source $VIMRUNTIME /delmenu.vim " 解决右键乱码source $VIMRUNTIME /menu.vim "解决consle输出乱码 language messages zh_CN.utf-8 " 设置默认保存位置exec 'cd ' . fnameescape("C:\\Users\\dell\\Desktop" ) set autochdir "自动识别当前打开文件路径 set pythonthreedll=" C:\Program Files\Python38\python38.dll "改成自己的版本 " set pythonthreehome ="C:\Program Files\Python38" set diffexpr =MyDiff()function MyDiff() let opt = '-a --binary ' if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif let arg1 = v:fname_in if arg1 =~ ' ' | let arg1 = '"' . arg1 . '"' | endif let arg2 = v:fname_new if arg2 =~ ' ' | let arg2 = '"' . arg2 . '"' | endif let arg3 = v:fname_out if arg3 =~ ' ' | let arg3 = '"' . arg3 . '"' | endif let eq = '' if $VIMRUNTIME =~ ' ' if &sh =~ '\<cmd' let cmd = '""' . $VIMRUNTIME . '\diff"' let eq = '"' else let cmd = substitute($VIMRUNTIME , ' ' , '" ' , '' ) . '\diff"' endif else let cmd = $VIMRUNTIME . '\diff' endif silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 . eq endfunction filetype on syntax on " 高亮 set cindent " C代码里需要的缩排set smartindentset autoindent " 自动缩进 set tabstop=4 " 修改 tab 字符的显示宽度set shiftwidth =4 " 自动缩进所使用的空白长度 set softtabstop=4 " set ts =4"set sw=4 " set sts =4"缩进 if $OS == 'Windows_NT' set mouse=a else set mouse-=a " Linux鼠标使用endif color molokai "colo desert " 主题set number " 行号 set guifont=Consolas:h15 " Linux: set guifont =Consolas\ h16set backspace =2set ruler " 显示标尺 " set bs =2set clipboard =unnamed " 共享剪切板 set go= " 不要图形按钮set nobackupset undofile " 保留历史撤销记录 " 括号补全inoremap ( ()<esc>i inoremap [ []<esc>i inoremap { {}<esc>i inoremap ' ' '<esc>i inoremap " ""<esc>i function! Compile() exec "w" if &filetype == ' python' exec "!python %" elseif &filetype == ' cpp' exec "!g++ % -o %< -std=c++11 -static-libgcc -Wall -g3" "exec "!g++ % -o %< -std=c++17 -static-libgcc -Wall -g3 -fexec-charset=GBK -finput-charset=UTF-8" elseif &filetype == ' c' exec "!g++ % -o %<" elseif &filetype == ' kotlin' exec "!kotlinc -d . %" elseif &filetype == ' java' exec "!javac %" else exec "!start %" endif endfunction function! Run() if &filetype == ' kotlin' exec "!kotlin %<Kt" elseif &filetype == ' java' exec "!java %<" elseif &filetype == ' go' exec "!go run %" else exec "!start %<" endif endfunction function! Open() exec "vsp %<.out" exec "sp %<.in" endfunction ":call libcallnr("vimtweak64.dll", "SetAlpha", 200) au GUIEnter * call libcallnr("vimtweak64.dll", "SetAlpha", 210) "自动透明 syntax enable map<F4> <Esc>:call Open() <CR> imap<F4> <Esc>:call Open() <CR> map<F9> <Esc>:call Compile() <CR> imap<F9> <Esc>:call Compile() <CR> map<F10> <Esc>:call Run() <CR> imap<F10> <Esc>:call Run() <CR> map<F11> <F9> <CR> <F10> <CR> imap<F11> <F9> <CR> <F10> <CR> " <CTRL>-w m : mark first window " <CTRL>-w m : swap with that window let s:markedWinNum = -1 function! MarkWindowSwap() let s:markedWinNum = winnr() endfunction function! DoWindowSwap() "Mark destination let curNum = winnr() let curBuf = bufnr( "%" ) exe s:markedWinNum . "wincmd w" "Switch to source and shuffle dest->source let markedBuf = bufnr( "%" ) "Hide and open so that we aren' t prompted and keep history exe 'hide buf' curBuf "Switch to dest and shuffle source->dest exe curNum . " wincmd w" " Hide and open so that we aren't prompted and keep history exe ' hide buf' markedBuf endfunction function! WindowSwapping() if s:markedWinNum == -1 call MarkWindowSwap() else call DoWindowSwap() let s:markedWinNum = -1 endif endfunction nnoremap <C-w>m :call WindowSwapping()<CR>
vim的四种模式
模式
说明
正常模式
默认,按 esc 进入,可复制粘贴、撤销重做
命令模式
正常模式下输入:或/进入,可进行保存、退出、搜索、运行
插入模式
按 i 进入,可进行输入编辑
可视模式
选中一块区域进行操作,按 v 进入
文件操作
命令
效果
:wq
保存并退出
:w 文件名
在当前路径下保存为指定文件
:q
退出
:q!
强制退出
移动
命令
效果
xw
光标向下移动x个单词
xb
光标向上移动x个单词
0
移动到行首
文本删除
命令(普通模式)
效果
dd
删除一行
de
从光标开始删除一个单词
dw
从光标开始删除一个单词(包括末尾空白)
dxw
删除x个单词
d$
删除到行末
dxd
删除x行
复制粘贴 按v进入可视模式,通过hjkl选择区域后,按下:y即可复制,在普通模式按p即可粘贴。
跳转
命令
效果
gg
跳转到第一行
G
跳转到最后一行
xG
跳转到第x行
[[
跳转到上一函数
%
跳转到匹配括号
/word\>
查找文本内所有word
:%s/foo/bar/g
全局替换foo为bar
:%s/foo/bar/gc
全局替换foo为bar并需要确认
编译
命令
效果
cpp test.cpp > test.i
将编译预处理结果(文本替换、宏展开以及删除注释)输入到test.i文件
g++ % -e %
同上
g++ -S %
使用指令编译成汇编代码
g++ tmp.cpp -o tmp -std=c++14 -static-libgcc -Wall -g3
编译
:10,20s#^#//#g
在 10 - 20 行添加 // 注释
:10,20s#^//##g
在 10 - 20 行删除 // 注释
STL vector 1 2 3 4 5 6 7 vec.size (); vector <int >(n); vec.empty (); vec.capacity (); vec.resize (n+m); sort (vec.begin (),vec.end (),cmp);reverse (vec.begin (), vec.end ());
list 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 c.size () 返回容器的大小 c.empty () 判断容器是否为空,等价于size ()==0 ,但可能更快 c.max_size () 返回容器最大的可以存储的元素 reserve () 如果容量不足,扩大之c.front () 返回第一个元素,不检查元素存在与否 c.back () 返回最后一个元素,不检查元素存在与否 c.begin () 返回一个逆向迭代器,指向逆向迭代的第一个元素 c.end () 返回一个逆向迭代器, 指向逆向迭代的最后一个元素的下一个位置 c.insert (pos, elem) 在迭代器pos所指位置上(前面)安插一个elem副本,并返回新元素的位置 c.insert (pos,n,elem) 在pos位置上插入n个elem副本,无返回值 c.push_back (elem) 在尾部添加一个elem副本 c.pop_back () 移除最后一个元素,无返回值 c.push_front () 在头部添加一个elem副本 c.pop_front () 移除第一个元素,但不返回 c.remove (val) 移除所有其值为val的元素 c.erase (pos) 移除pos位置上的元素,返回下一个元素的位置 c.unique () 如果存在若干相邻而数值相等的元素,就移除重复元素,只留下一个 c.sort (op) 以op ()为准则,对所有元素排序 c1.merge (c2,op) 假设c1和c2容器都包含op ()原则下的已序(相同的排序方式)元素,将c2的全部元素转移到c1,并保证合并后的list在op()原则仍是已序。 c.reverse () 将所有元素反序
set 1 2 3 4 5 6 7 8 9 10 11 12 13 multiset可重集,都为红黑树实现 begin () 返回set容器的第一个迭代器,不检查set是否为空end () 返回set容器的最后一个迭代器,不检查set是否为空clear () 删除set容器中的所有的元素empty () 判断set容器是否为空,复杂度O (1 )max_size () 返回set容器可能包含的元素最大个数size () 返回当前set容器中的元素个数,复杂度O (1 )set.count (x) 返回set或multiset中值为x的元素个数,复杂度O (log n) set.insert (x) 插入元素,返回插入地址的迭代器和是否插入成功的bool 并成的pair,复杂度O (log n) erase (参数) 删除,参数可以是元素或者迭代器,返回下一个元素的迭代器,复杂度O (log n)set.find (x) 在set中查找值为x的元素,并返回指向该元素的迭代器,若不存在,返回set.end (),复杂度O (log n) lower_bound (x) 返回第一个大于等于x的定位器upper_bound (x) 返回最后一个大于等于x的定位器
函数 max_element与min_element 1 2 3 4 5 template < class ForwardIt >ForwardIt max_element (ForwardIt first, ForwardIt last ) ;template < class ForwardIt, class Compare >ForwardIt max_element (ForwardIt first, ForwardIt last, Compare comp ) ;nth_element (first,nth,last,cmp)
scanf格式化输入
转换说明符
意义
%d,%i
把输入解释为一个有符号十进制整数
%o
把输入解释为一个有符号八进制整数
%x,%X
把输入解释为一个无符号十六进制整数
%p
把输入解释为一个指针(一个地址)
[]
字符集合
[]里面填写需要捕获的字符集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 char buf[20 ];scanf ("%[abc]" , buf); scanf函数匹配[]中的所有字符,直到找到一个非[]中的字符 []中也可以填写字符范围,例如 [a-z] [a-zA-Z] [0 -9 ] [a-zA-Z0-9 ]捕获所有字母和数字 [a-zA-Z0-9 !]捕获所有字母和数字并且捕获!(感叹号) []中如果第一字符为^符号则表示出现[]中的内容则停止捕获,并且仍然留在缓冲区,例如 [^a-zA-Z]捕获非字母 [^0 -9 ]捕获非数字 scanf (" %[^\n]" ,s);
十进制转任意进制itoa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 char * itoa (int num,char * str,int radix) { char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; unsigned unum; int i=0 ,j,k; if (radix==10 &&num<0 ) { unum=(unsigned )-num; str[i++]='-' ; } else unum=(unsigned )num; do { str[i++]=index[unum%(unsigned )radix]; unum/=radix; }while (unum); str[i]='\0' ; if (str[0 ]=='-' ) k=1 ; else k=0 ; char temp; for (j=k;j<=(i-1 )/2 ;j++) { temp=str[j]; str[j]=str[i-1 +k-j]; str[i-1 +k-j]=temp; } return str; }
对拍 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int main () { int i; for (i=1 ;i<=1000 ;i++) { system ("./make" ); system ("./ab1" ); system ("./ab2" ); printf ("%d : " ,i); if (system ("diff ab1.out ab2.out" )) { printf ("WA\n" ); return 0 ; } else printf ("AC\n" ); } return 0 ; }