OIer复健记录
Day1 2020.7.18
[数据类型]
·包括读入,输出,保留,对齐等
·int,char,double,long double,float,long long,short
[最大公因数,最小公倍数]
写法是这样的来着?
Day2 2020.7.22 我太水了
·freopen
·dfs
·质数判断
·memset,memcpy,sort之类的STL
·埃及分数(思路错了,我用double写的,GG)
Day3 2020.8.2 我是最水的
·memset的各种赋值(之前写的博客终于有用了哦哦哦)
·lower_bound(a,a+n,x) //查找>=x的第一个位置
·vector<int> a : sort( a.begin() , a.end() ), a.size(), a.resize(), a.push_back(), a.pop_back(), a.clear(), a.empty()
vector之间可直接赋值或作为函数返回值
Day4 2020.8.5 我还是很水
·STL里set&map的使用
·栈,队列,优先队列(STL里也有,但自己写的比较快吧):push的反义词是pop!
关于priority_queue的重载运算符
struct cmp{ bool operator()(const int a,const int b)const{ return a>b;//a比b的优先级小的时候返回True } }
·快读:主要是用while进行getchar(),还有要用ch<<1+ch<<3+ch^48加速,ch^48相当于ch-=‘0’
inline int rd(){ ans=0; ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9'){ ans=(ans<<1)+(ans<<3)+(ch^48); ch=getchar(); } return ans; }
·线段树:先贴个自己的板子
#include <cstdio> #define ll long long #define maxn 1000010 #define mid ((l+r)>>1) #define lson x<<1 #define rson x<<1|1 int n,m,opr,a,b,c; int len[maxn]; ll sum[maxn],flag[maxn]; void push_up(int x){ sum[x]=(sum[lson]+sum[rson]); } void build(int x,int l,int r){ len[x]=r-l+1; if(l==r){ scanf("%lld",&sum[x]); return; } build(lson,l,mid); build(rson,mid+1,r); push_up(x); return; } void push_down(int x){ flag[lson]+=flag[x]; flag[rson]+=flag[x]; sum[lson]+=flag[x]*len[lson]; sum[rson]+=flag[x]*len[rson]; flag[x]=0; } void add(int x,int cl,int cr,int l,int r,int val){//cl,cr为需要修改的区间 push_down(x); if(cl==l&&r==cr){ flag[x]+=val; sum[x]+=(r-l+1)*val; return; } if(cr<=mid) add(lson,cl,cr,l,mid,val); else if(cl>mid) add(rson,cl,cr,mid+1,r,val); else add(lson,cl,mid,l,mid,val),add(rson,mid+1,cr,mid+1,r,val); push_up(x); return; } ll query(int x,int cl,int cr,int l,int r){ push_down(x); if(cl==l&&r==cr){ return sum[x]; } ll ret=0; if(cr<=mid) ret+=query(lson,cl,cr,l,mid); else if(cl>mid) ret+=query(rson,cl,cr,mid+1,r); else ret+=query(lson,cl,mid,l,mid),ret+=query(rson,mid+1,cr,mid+1,r); return ret; } int main(){ scanf("%d%d",&n,&m); build(1,1,n); for(int i=1;i<=m;i++){ scanf("%d%d%d",&opr,&a,&b); if(opr==1){ scanf("%d",&c); add(1,a,b,1,n,c); continue; } printf("%lld\n",query(1,a,b,1,n)); } return 0; }
Day5 2020.8.6 小水孩做小水题
·洛谷P1890 gcd区间 线段树数组开小了,结果惨遭RE(已AC)
·CF229B 开始图论讨伐!先拿SPFA开刀好了,存图从vector改成了链式前向星 (艰难地AC了,这题数据设置的有点坑)
诶,什么,你说SPFA已经死了?Σ(っ °Д °;)っ
卡SPFA的人都坏坏!
void spfa(){ dis[1]=0,in[1]=1,q.push(1); while(!q.empty()){ tp=q.front(),q.pop(),in[tp]=0; tval=dis[tp]; while(s[tp].count(tval)) tval++; for(int i=head[tp];~i;i=e[i].nxt){ nw=e[i].to; if(tval+e[i].w<dis[nw]){ dis[nw]=tval+e[i].w; if(!in[nw]) q.push(nw),in[nw]=1; } } } }
·在terminal中复制(Ctrl+Insert)、粘贴(Shift+Insert)
Day6 2020.8.7 菜菜今天也要加油( •̀ ω •́ )y
·堆优化Dijkstra,讨伐开始!注:dijkstra不能跑负权环和最长路,最长路的贪心是错的
#include<stdio.h> #include<queue> #include<algorithm> #include<iostream> using namespace std; int nex[400001]; int to[400001]; int val[400001]; int head[200001]; int f[200001]; int idx,x,y,z; int inf=2147483647; bool vis[200001]; struct Point { int number,dis; inline bool operator < (const Point &a) const { return dis>a.dis; } }; priority_queue <Point> q; void addedge(int a,int b,int c) { nex[++idx]=head[a]; head[a]=idx; to[idx]=b; val[idx]=c; } int n,m,s; int main() { Point tmp; scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); addedge(x,y,z); } for(int i=1;i<=n;i++) f[i]=inf; tmp.number=s,tmp.dis=0; f[tmp.number]=0; q.push(tmp); while(!q.empty()) { int here=q.top().number; q.pop(); if(vis[here]) continue; vis[here]=1; for(int j=head[here];j;j=nex[j]) if(f[to[j]]>val[j]+f[here]&&(!vis[to[j]])) { f[to[j]]=f[here]+val[j]; tmp.number=to[j]; tmp.dis=f[to[j]]; q.push(tmp); } } for(int i=1;i<=n;i++) printf("%d ",f[i]); }
·拓扑排序 码是随便写的,凑一下工作量
#include <queue> #include <cstdio> #define N 10005 using namespace std; queue<int> q; bool vis[N]; int a,b,n,m,tmp,cnt,in[N]; int head[N],to[N],nxt[N]; inline void add(int u,int v){ nxt[++cnt]=head[u]; to[cnt]=v,head[u]=cnt; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d",&a,&b); add(a,b),in[b]++; } for(int i=1;i<=n;i++){ if(!in[i]) q.push(i),vis[i]=1; } while(!q.empty()){ tmp=q.front(),q.pop(); printf("%d ",tmp); for(int i=head[tmp];i;i=nxt[i]){ if(vis[to[i]]) continue; in[to[i]]--; if(!in[to[i]]) q.push(to[i]),vis[to[i]]; } } return 0; }
·[无向图的欧拉回路]
欧拉道路:如果一个无向图是连通的,且最多只有两个奇点,则一定存在欧拉道路。如果有两个奇点,则必须从一个奇点出发,以另一个奇点结束。
欧拉回路:如果奇点不存在,则可以从任意点出发,最终一定会回到该点。
[有向图的欧拉回路]
最多只能有两个点的入度≠出度,且一个多1,另一个少1;忽略边的方向后,图必须联通
·Tarjan 缩强连通分量 没完全理解(可能之前也没完全搞懂,印象不是很深),明天接着来
Day7 2020.8.8 看看今天能学多少
摸了,仍然没理解Tarjan,倒是颓了不少深圳I/O!qwq
Day8 2020.8.9 今天不能再划水了
·Tarjan讨伐!贴个讲解 https://zhuanlan.zhihu.com/p/101923309
啊......递归里面开全局变量一定要小心——调码半小时有感
#include <cstdio> #include <algorithm> #define N 100005 using namespace std; struct Answer{ int u,v; }ans[N]; bool is_bridge[N]; int n,m,nw,num,cnt=1,val[N]; int a,b,head[N],to[N],nxt[N]; int low[N],dfn[N],ans_tot,edge_tot; void add(int a,int b){ nxt[++cnt]=head[a]; head[a]=cnt,to[cnt]=b; } void tarjan(int s,int edge){ low[s]=dfn[s]=++num; for(int i=head[s];i;i=nxt[i]){ int nw=to[i]; if(!dfn[nw]){ tarjan(nw,i); low[s]=min(low[s],low[nw]); if(low[nw]>dfn[s]){ is_bridge[i]=is_bridge[i^1]=1; } } else if(i!=(edge^1)) low[s]=min(low[s],dfn[nw]); } } bool cmp(Answer x,Answer y){ if(x.u==y.u) return x.v<y.v; return x.u<y.u; } // bool operator <(const Answer x,const Answer y){ // if(x.u==y.u) return x.v<y.v; // return x.u<y.u; // } int main(){ scanf("%d%d",&n,&m); for(int i=0;i<m;i++){ scanf("%d%d",&a,&b); add(a,b),add(b,a); } for(int i=1;i<=n;i++){ if(!dfn[i]) tarjan(i,0); } edge_tot=m*2+1; for(int i=2;i<edge_tot;i+=2){ if(is_bridge[i]){ ans[++ans_tot].u=to[i^1]; ans[ans_tot].v=to[i]; if(ans[ans_tot].u>ans[ans_tot].v) swap(ans[ans_tot].u,ans[ans_tot].v); } } sort(ans+1,ans+ans_tot+1,cmp); for(int i=1;i<=ans_tot;i++){ printf("%d %d\n",ans[i].u,ans[i].v); } return 0; }
我居然被sort卡了一上午(忘+1了),啊
·比较函数写法 https://blog.csdn.net/witnessai1/article/details/47395551