NOIp2017——追求那些我一直追求的
谨以此祭奠我即将爆炸的NOIP2017.
$Mingqi\_H\ \ 2017.09.24$
Day -47
突然发现半年来自己从来没有写对过SPFA,最近几天才发现自己的板子一直是错的...赶紧找个例题修一下板子:
1 #include<cstring> 2 #include<cstdio> 3 #include<queue> 4 using namespace std; 5 const int maxn = 1e6+10; 6 struct Edge{ 7 int u,v,w; 8 }edge[maxn*2]; 9 int head[maxn]; 10 int cnt; 11 int dis[maxn],vis[maxn]; 12 int m,n; 13 inline void add(int u,int v,int w) 14 { 15 edge[++cnt].u=head[u]; 16 edge[cnt].v=v; 17 edge[cnt].w=w; 18 head[u]=cnt; 19 return; 20 } 21 void spfa(int p) 22 { 23 memset(dis,0x3f,sizeof(dis)); 24 memset(vis,0,sizeof(vis)); 25 int cur,nxt,v; 26 queue<int> q; 27 while(!q.empty()) 28 q.pop(); 29 q.push(p),vis[p]=true; 30 dis[p]=0; 31 while(!q.empty()) 32 { 33 cur=q.front(),q.pop(),vis[cur]=false; 34 for(int i=head[cur];i;i=edge[i].u) 35 { 36 v=edge[i].v; 37 if(dis[p]+edge[v].w<dis[v]) 38 { 39 dis[v]=dis[p]+edge[v].w; 40 q.push(v),vis[v]=true; 41 } 42 } 43 } 44 for(int i=1;i<=m;i++) 45 printf("%d ",dis[i]); 46 printf("\n"); 47 return; 48 } 49 int main() 50 { 51 int u,v,w; 52 scanf("%d%d",&m,&n); 53 for(int i=0;i<n;i++) 54 { 55 scanf("%d%d%d",&u,&v,&w); 56 add(u,v,w); 57 } 58 for(int i=1;i<=m;i++) 59 spfa(i); 60 }
问题:学了这么久了都不会建邻接链表,SPFA加的是点,不是边,链表链表,head数组和edge数组要连起来,第一行是$edge[++cnt].u=head[u];$最后一行是$head[u]=cnt;$永远记住!!!这不是一年前了!!!
你基础不牢啊,吃枣药丸,吃枣药丸,之前还有200多天的时候,你跟现在的水平差不多啊。这100多天你干什么了?!之前不是经常拿到$Rank\ 1$吗?那个你呢?你模拟赛两次四天12道题,分数加起来还没人家一天3道题的多,你会什么啊?会数论吗?之前一直认为自己能拿到$Day2\ T1$的100分,模拟赛那么简单的一道数论题你可是一分都没拿到啊!!!该好好反思一下了!!你不会DP,也就算了,可是你连暴力也不会打,这就说不过去了吧,三四个月前建立的分类,结果到现在也没整理几个题啊,别人的Blogs都有几百道题目了啊!你总共过了有400题吗?!去重之前也仅仅有386道啊!!!还有100多道OJ上的题目,你这一年多干了些什么!
还是从板子开始吧,不能温水煮青蛙了,不能这样下去了。
Kruskal写的也不好,注意不是邻接链表了,是最最普通的数组了,不是邻接表!!!没必要写add_edge!!!写上邻接表的就错了!!!并查集也得背背啊。还有,那个sort对结构体排序还得练一练,都忘得差不多了,必要的话,重新看看OJ上的那几道题目。
#include<cstdio> #include<algorithm> using namespace std; #define maxp 5005 #define maxe 200005 struct Edge{ int u,v,w; }edge[maxe]; inline int cmp(Edge a,Edge b){return a.w<b.w;} int cnt; int fat[maxp]; inline int find(int x) {return fat[x]!=x?fat[x]=find(fat[x]):fat[x];} inline void unionn(int x,int y) {int fa=find(x),fb=find(y);if(fa!=fb)fat[fa]=fb;} int n,m; inline void Kruskal() { sort(edge+1,edge+m+1,cmp); int k=0,ans=0; for(int i=1;i<=m;i++) { if(find(edge[i].u)!=find(edge[i].v)) { unionn(edge[i].u,edge[i].v); ans+=edge[i].w; k++; } } if(k<n-1) printf("orz"); else printf("%d",ans); return; } int main() { int u,v,w; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) fat[i]=i; for(int i=1;i<=m;i++) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); Kruskal(); return 0; }
复习计划:
NOIP范围内所有的知识点,包括数论。重点放在图论、数论、不熟练的知识点(贪心、动规、分治、二分、搜索等),时间:30d.对于其他较少考到的以及高级的内容(中高级数据结构、STL等),短期内全部不涉及,没有时间对那些较难并且没用的东西进行学习了,这不是省选前半年可以停课随便搞的时间了,毕竟马上就要考试了。
保证无论何时、无论有什么情况,每天保证至少学习1h,大周回家至少拿出2h写板子。NOIP前不再学习新的知识了。
Day-45
今天检验之前的SPFA,发现依旧不对……赶紧改过来……
1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 #define maxn 1000001 5 using namespace std; 6 struct Edge 7 { 8 int u,v,w; 9 } edge[2*maxn]; 10 int head[maxn],cnt; 11 int n,m; 12 int vis[maxn],dis[maxn],cur,nxt; 13 inline void add(int u,int v,int w) 14 {edge[++cnt].u=head[u],edge[cnt].v=v,edge[cnt].w=w,head[u]=cnt;} 15 inline void spfa(int u) 16 { 17 queue<int>q; 18 memset(vis,0,sizeof(vis)), 19 memset(dis,0x3f,sizeof(dis)), 20 dis[u]=0; 21 while(!q.empty())q.pop(); 22 vis[u]=true,q.push(u); 23 while(!q.empty()) 24 { 25 cur=q.front(),vis[cur]=0,q.pop(); 26 for(int i=head[cur]; i; i=edge[i].u) 27 { 28 int v=edge[i].v; 29 if(dis[v]>dis[cur]+edge[i].w) 30 { 31 dis[v]=dis[cur]+edge[i].w; 32 if(!vis[v]) 33 vis[v]=1,q.push(v); 34 } 35 } 36 } 37 for(int i=1; i<=m; i++) 38 printf("%d ",dis[i]); 39 printf("\n"); 40 return; 41 } 42 int main() 43 { 44 int u,v,w; 45 scanf("%d%d",&m,&n); 46 for(int i=0; i<n; i++) 47 { 48 scanf("%d%d%d",&u,&v,&w); 49 add(u,v,w); 50 } 51 for(int i=1; i<=m; i++) 52 spfa(i); 53 return 0; 54 }
???
1 #include<cstdio> 2 #include<cstring> 3 #define maxn 1000001 4 using namespace std; 5 struct Edge 6 { 7 int u,v,w; 8 } edge[2*maxn]; 9 int head[maxn],cnt; 10 int n,m; 11 int vis[maxn],dis[maxn],cur,nxt; 12 inline void add(int u,int v,int w) 13 {edge[++cnt].u=head[u],edge[cnt].v=v,edge[cnt].w=w,head[u]=cnt;} 14 struct queue{ 15 int array[4*maxn]; 16 int h,t; 17 inline bool empty(){return h>=t;} 18 inline void push(int x){array[h++]=x;} 19 inline void pop(){t--;} 20 inline int front(){return array[h];} 21 inline void clear(){h=t=0;} 22 }q; 23 inline void spfa(int u) 24 { 25 memset(vis,0,sizeof(vis)), 26 memset(dis,0x3f,sizeof(dis)), 27 dis[u]=0; 28 q.clear(); 29 vis[u]=true,q.push(u); 30 while(!q.empty()) 31 { 32 cur=q.front(),vis[cur]=0,q.pop(); 33 for(int i=head[cur]; i; i=edge[i].u) 34 { 35 int v=edge[i].v; 36 if(dis[v]>dis[cur]+edge[i].w) 37 { 38 dis[v]=dis[cur]+edge[i].w; 39 if(!vis[v]) 40 vis[v]=1,q.push(v); 41 } 42 } 43 } 44 for(int i=1; i<=m; i++) 45 printf("%d ",dis[i]); 46 printf("\n"); 47 return; 48 } 49 int main() 50 { 51 int u,v,w; 52 scanf("%d%d",&m,&n); 53 for(int i=0; i<n; i++) 54 { 55 scanf("%d%d%d",&u,&v,&w); 56 add(v,u,w);//无向图 57 add(u,v,w); 58 } 59 for(int i=1; i<=m; i++) 60 spfa(i); 61 return 0; 62 }
Day-44
今天手打了一遍SPFA,然而边表又建错了...是$edge[++cnt].u=head[u];$不是$edge[cnt++].u=head[u];$
今天复习LCA吧...看起来queue与手写队列效率差不多,对于随机数据两个都差不多,deque更慢了,对于$10^9$的数据效率差了50ms左右。
1 #include<cstdio> 2 using namespace std; 3 #define maxn 500010 4 int n,m,s,f[maxn][22],deep[maxn],head[maxn],num; 5 struct node 6 { 7 int to,pre; 8 } e[maxn<<1]; 9 void Insert(int from,int to){e[++num].to=to;e[num].pre=head[from];head[from]=num;} 10 void find_deep(int from,int now,int dep) 11 { 12 f[now][0]=from; 13 deep[now]=dep; 14 for(int i=head[now]; i; i=e[i].pre) 15 if(e[i].to!=from) 16 find_deep(now,e[i].to,dep+1); 17 } 18 void find_father() 19 { 20 for(int j=1; j<=21; j++) 21 for(int i=1; i<=n; i++) 22 f[i][j]=f[f[i][j-1]][j-1]; 23 } 24 int get(int a,int delta) 25 { 26 for(int i=0; i<=21; i++) 27 if(delta&(1<<i))a=f[a][i]; 28 return a; 29 } 30 int lca(int a,int b) 31 { 32 if(deep[a]<deep[b]) swap(a,b); 33 a=get(a,deep[a]-deep[b]); 34 if(a==b) return a; 35 for(int i=21; i>=0; i--) 36 if(f[a][i]!=f[b][i]) 37 a=f[a][i],b=f[b][i]; 38 return f[a][0]; 39 } 40 int main() 41 { 42 scanf("%d%d%d",&n,&m,&d); 43 int x,y; 44 for(int i=1; i<=n-1; i++) 45 { 46 scanf("%d%d",&x,&y); 47 Insert(x,y),Insert(y,x); 48 } 49 find_deep(s,s,0); 50 find_father(); 51 for(int i=1; i<=m; i++) 52 { 53 scanf("%d%d",&x,&y); 54 printf("%d\n",lca(x,y)); 55 } 56 return 0; 57 }
Day-43
LCA是什么???Tarjan||倍增||树链剖分???
玩一玩树状数组好了。
我什么都不会...
#define lowbit(__x__) (__x__&(-__x__)) //区间查询单点修改不需要差分数组。 //区间查询时需要查询两个端点,调用query(y)-query(x-1)。 inline int query(int x){int ans=0;for(int i=x;i>0;i-=lowbit(i))ans+=c[i];return ans;} inline void modify_point(int x,int d){for(int i=x;i<=n;i+=lowbit(x))c[i]+=d;} //区间修改单点查询需要差分数组。两者有一些不同。 //初始化树状数组时就需要差分处理,用一个pre变量记录前一个元素,然后调用modify(place,x-pre)。 //区间修改直接在差分数组上进行,仅需要修改两个端点即可,调用modify(point,k),modify(point,-k)。 //查询基本相同。 inline void modify_interval(int x,int d){for(int i=x;i<=n;i+=lowbit(i))a[i]+=d;}
Day-42
今天忙,坐一整天车,晚上做了作业。
Day-41
一个弱省蒟蒻,为何到北京?
昨日来京,腰酸背痛。今天开始考试了。然而貌似挂得很惨,T1爆零了2333...还是弱啊,晚上写题解。下午主要讲搜索的技巧。表示双向BFS还是不会。还是去看看搜索大题吧。
Rank 69...看起来T1可以拿到60分左右2333...
Day-40
2333...标日没收了2333...hhh
然而今天题目没区分度...大众分60分...打个表就有了..
不想搞事情了...qbxt真的不是很适合我...回去搞一搞浴谷...
噫...什么时候漏下了一天...好像是回家的那一天???今天应该是Day-39...药丸...赶紧看看LCA与线段树...
据说快停课了...表示好方...
下定决心来一遍LCA...
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int N = 500100; 5 int fa[N][25],dep[N]; 6 struct Edge{int to,nxt;}e[N*2]; 7 int head[N],cnt; 8 inline void add(int u,int v){e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt;} 9 int n,maxdep,T,rt,top; 10 void build(int u) 11 { 12 for(int i=head[u];i;i=e[i].nxt) 13 { 14 int v=e[i].to; 15 if(v!=fa[u][0]) 16 { 17 fa[v][0]=u; 18 dep[v]=dep[u]+1; 19 maxdep=max(maxdep,dep[v]); 20 build(v); 21 } 22 } 23 } 24 inline int LCA(int u,int v) 25 { 26 if(dep[u]<dep[v])swap(u,v); 27 for(int k=top;k>=0;k--) 28 if(dep[fa[u][k]]>=dep[v]) 29 u=fa[u][k]; 30 if(u==v) 31 return u; 32 for(int k=top;k>=0;k--) 33 if(fa[u][k]!=fa[v][k]) 34 u=fa[u][k],v=fa[v][k]; 35 return fa[u][0]; 36 } 37 int main() 38 { 39 scanf("%d%d%d",&n,&T,&rt); 40 for (int i=1; i<n; i++) 41 { 42 int u,v; 43 scanf("%d%d",&u,&v); 44 add(u,v),add(v,u); 45 } 46 dep[rt]=1; 47 build(rt); 48 for (; (1<<top)<=maxdep; top++); 49 for (int k=1; k<=top; k++) 50 for (int i=1; i<=n; i++) 51 fa[i][k]=fa[fa[i][k-1]][k-1]; 52 while (T--) 53 { 54 int u,v; 55 scanf("%d%d",&u,&v); 56 printf("%d\n",LCA(u,v)); 57 } 58 return 0; 59 }
只会倍增的我...
Day-39
NOIP模拟赛,Day1难度,20分。
文件文件,引用cstdio库...T1正解都没想出来,太弱啊。
目前的坑:简单的模拟,线段树,dp,文件.
Day-38
NOIP模拟赛,Day2,10分。
文件错误。
目前新增的坑:...太多了...
Day-37
NOIp模拟赛,100分。
蜜汁T1没分,long long炸了。
T2是数据的锅,当然手动拍了一下感觉没什么问题(算法误判率在1‰左右吧),交上竟然A了。
不过今天是数论专场,有dalao AK了,100分也不算高,在50%左右吧。
希望明天rp++,不要出锅。
最后还是因为⑨啊。
Day-31
信息课上来打代码...惨啊...
二区停课了...我们为什么不停...要死啊...
看看LCA什么的...千万别出锅...
另外等着父亲的消息2333...实在不行先暂时通校?鬼知道呢...
昨天去淄博,逛了MUJI的店,然而掉坑里去了...
晚上请假回家,做LCA的板子。线段树什么的还需要复习一下。感觉药丸。
距 NOIp2017 还剩 31 天
Day-30
神TM昨天晚上十一点半睡觉2333...然而写了6k+代码,感觉不错的说...
然而今天快困死了TM...
住校也好不到哪里去据说...
快初赛了...略紧张...虽然知道是买试卷,然而复赛并不有什么把握...
Day-29
今天是历史性的一天。晚上成功申请下来停课了,接下来的日子当然是要好好学习了。后天将面临初赛,RP++!
Day-28
并没有停课,还是回来吧,明天初赛2333.开始背背板子吧。
Day-19
gg...还有3个周...方方方...
Day-12
还有不到2w了,终于停课了,然而两天模拟4场考试完挂。∑=180+0+40+40=260.
Day2 T1T2都想到正解了,然而写挂。哎,自己弱写挂怪谁。
晚上还是好好整理一下吧。
Day-10
还有10d,自己仍然什么都不会,两天模拟赛∑=0+40+0+30=70
已经绝望了。
Day-9
似乎今天被续了1s,加起来得分超过Day-10+Day-11两天的了。
短期内水平可能不会有太多进步了吧。
Day-5
昨天回家翻说说,QBXT校长王彪竟然没有看出来glgjssy,qyhfbqz这一句的含义???蛤蛤蛤蛤蛤蛤。
完蛋了,自己还是什么都不会。这几天打打板子,然后好好整理一下。
1111&&1112那两天考试,当然要抽时间把Magical Mirai 2017补完(似乎今年Vmoe出片比较快???)。
重写了线段树,区间操作47行。然而似乎还是没背过。再看看树状数组。
const int maxn=2*1e7+10;//max node: 5*1e6 long long sum[maxn];//real long long addv[maxn];//lazy-tag long long c[maxn/4]; #define mid ((l+r)>>1) #define lson (o<<1) #define rson (lson|1) inline void build(int o,int l,int r) { addv[o]=0; if(l==r)sum[o]=c[l]; else { build(lson,l,mid); build(rson,mid+1,r); sum[o]=sum[lson]+sum[rson]; } } inline void push_down(int o,int l,int r) { addv[lson]+=addv[o]; addv[rson]+=addv[o]; sum[lson]+=(mid-l+1)*addv[o]; sum[rson]+=(r-mid)*addv[o]; addv[o]=0; } inline void update(int o,int l,int r,int a,int b,int x) { if(l>=a&&r<=b) { addv[o]+=x; sum[o]+=(r-l+1)*x; return; } if(addv[o])push_down(o,l,r); if(a<=mid)update(lson,l,mid,a,b,x); if(b>mid)update(rson,mid+1,r,a,b,x); sum[o]=sum[lson]+sum[rson]; } inline long long query(int o,int l,int r,int a,int b) { if(l>=a&&r<=b)return sum[o]; long long ans=0; if(addv[o])push_down(o,l,r); if(a<=mid)ans+=query(lson,l,mid,a,b); if(b>mid)ans+=query(rson,mid+1,r,a,b); return ans; }
想想线段树还有哪些神奇的操作吧。维护区间最大值最小值什么的也要写。不会ST表可以这样水一下。
Floyd都不会了,重新背一遍吧。
二分的话,前一段时间集训有一大堆,整理一下,总结一下套路吧。
Day-4
今天去竞赛楼整理书,乱七八糟的,丢了一大堆东西,都不知道放在哪里了。rp--。
下午找了一下,竟然在船运传运办公室,东西似乎没丢,rp++.
重做NOIp2016,365分。感觉还好,特别是临时补完复习了期望那些东西,然后成功多得100分。
考试的时候千万别忘记建子文件夹,千万别忘记建子文件夹,千万别忘记建子文件夹!!!
随手写个gcd玩玩。
#include<cstdio> using namespace std; int a,b; int gcd(int a,int b){return !b?a:gcd(b,a%b);} int main() { scanf("%d%d",&a,&b); printf("%d",gcd(a,b)); return 0; }
线性筛素数:
#include<cstdio> using namespace std; const int N=10000000+10; bool flag[N]; int prime[N]; inline void get_prime(int x) { flag[1]=1; int i,j,k=0; for(i=2;i<=x;i++){//注意不能用小于号,否则会WA成SB!!! if(!flag[i]) prime[k++]=i; for(j=0;j<k&&i*prime[j]<=x;j++){//注意不能用小于号,否则会WA成SB!!! flag[i*prime[j]]=true; if(i%prime[j]==0) break; } } } int n,m,q; int main() { scanf("%d%d",&n,&m); get_prime(n); for(int i=0;i<m;i++) { scanf("%d",&q); printf(!flag[q]?"Yes\n":"No\n"); } return 0; }
换个背景玩玩,全是蓝色基调的背景太难看了。NOIp后再调整一下博客吧。
void exgcd(int a,int b,int &d,int &x,int &y) { if(!b) {d=a;x=1;y=0;} else {gcd(b,a%b,d,y,x);y-=x*(a/b);} }
当然如果您的浏览器版本不行的话,背景什么的会死的很惨。2333333
Day-3
绝望,已经不知道自己在干什么了。
二区的老师给我们各种压力,明年有5个进队的blahblah。。。
TM你们怎么不先去死。
各种出锅,各种不会,矩阵是什么?
调了一下午矩阵的东西,不知道哪里错了。。。
20分。
还TM考什么NOIp啊...弃疗算了。
回来第二天就要期中考试,考(及)好(格)的概率,不存在的。
我到底在做什么???
Day-2
已经没救了,模拟都会挂掉。Orz...
Day-1
今天上午考的还可以。200分。继续做课件了。源代码60K+,已经没救了。
晚上继续矩阵乘法,WA成SB...原因竟是忽略了矩阵乘法不具有交换律。
SB啊!!!
矩阵快速幂、乘法:
#include<cstdio> #include<vector> using namespace std; typedef vector<long long> vec; typedef vector<vec> matrix; typedef long long ll; long long p,q,a1,a2,n,m; matrix operator *(const matrix &A,const matrix&B) { matrix C(A.size(),vec(B[0].size())); for(int i=0;i<A.size();i++) for(int k=0;k<B.size();k++) for(int j=0;j<B[0].size();j++) C[i][j]=(C[i][j]+A[i][k]*B[k][j])%m; return C; } matrix pow(const matrix&A,ll n) { matrix B(A.size(),vec(A.size())); for(int i=0;i<A.size();i++) B[i][i]=1; while(n) { if(n&1)B=B*A; A=A*A; n>>=1; } return B; } int main() { scanf("%lld%lld%lld%lld%lld%lld",&p,&q,&a1,&a2,&n,&m); matrix A(2,vec(2)); A[0][0]=p;A[0][1]=1; A[1][0]=q;A[1][1]=0; matrix B(1,vec(2)); B[0][0]=a2,B[0][1]=a1; A=pow(A,n-2); A=B*A; printf("%lld\n",A[0][0]); return 0; }
Day0
最后一天了。还是什么都不会。
Day1
T1,这是什么题啊,不送分了啊。方方方。5min推出规律,跟暴力拍,哦漏,拍一组挂一组是什么鬼啊。gg,改成暴力。
T2,模拟吧这是。。。疯狂写写写。
(1h later...)MMP什么东西啊,不过样例是什么鬼啊。不写了,开始调试。
(45min. later)MMP还是不过样例啊。完了完了。
T3,?????什么都不会,完蛋了。
(回到RZYZ后:MMP我准考证呢!!!啊啊啊啊药丸药丸啊!!!)
吃晚饭的时候发现xps开不了机(mmp,关键时候掉链子啊),在食堂重置电脑(2333...边充电边重置)。。。
晚上开始颓Magical Marai 2017...没电了就睡了。
Day2
(回到考场老师把准考证还给我了2333...)
T1,三维计算几何???不可做不可做。(读错题flag)随便骗骗分吧(20 pts. get)。
T2,Kruskal重构树,然后DFS计算深度乱搞???不搞了,最后那个数据结构题看起来比较可做啊,先去看看。
T3,先写个暴力,拿30分???
(15min. later)woc...为什么炸了...开始调试。
(30min. later)这,也太容易了吧,随手过样例和大样例啊。
(35min. later)woc...这个暴力炸了,我n和m不分啊,这随机造的数据炸了啊。
(45min. later)终于调完了。考虑一下较高的暴力分吧。
(50min. later)嗯...可以用链表写一下,拿60分吧。
(1.3h later)链表写完了,啊,过了手造的样例。60分应该稳了。
(1.4h later)MMP忘记删if else了,所以刚才的链表实际上是个暴力???删掉看看。
(1.5h later)炸了炸了。交暴力吧,不调了。
转回来做T2,此时距离考试结束还剩40min.
随便写写吧,反正是做不完了。
(35min. later)写完了吧。代码长度1.7k+,非正解啊啊啊啊。不调了,心态爆炸。
颓吧。
11.15
清北数据成绩:100+0+0+0+0+30=130
洛谷数据成绩:100+10+0+20+0+30=160
学军数据成绩:100+0+0+0+0+30=130
完美挂掉。