[總結] NOIP 前的考試記錄
阿新 • • 發佈:2018-07-14
mes tdi val cas lin 寫在前面 down show latex
寫在前面
由於我天天被虐,模擬考還老是考的極差,感覺有必要開個博客記錄一下每場考試
由於懶得加美元符所以這篇博客不用 latex
由於要弄代碼折疊我還特意換掉了 Markdown 編輯器
由於我沒話說了,前言就這麽多吧
2018.7.13
開場看 T1 發現不會頓時賊虛,思路明明馬上就是正解了但是死活沒想出來。把點權放到邊上求出來最大生成樹之後立馬敲了個樹剖(我只是生來碼農) 然後跟暴力一樣 n^2 求的兩點邊權最小值
看 T2 也是發現性質可以開兩個樹狀數組做但是死活沒想出來答案從哪找,結果發現莫隊一臉可做碼了個帶修莫隊還把塊大小設成根號 n 了。(我果然菜到連前一天剛講過的板子都不會敲了
結果 T2 被卡但是還是比暴力多 20 分
T3 更不可做 直接30分爆搜走人
總分 50+50+30=130 本部 rank3/16
T1 這東西應該能發現可以從大到小加邊合並集合啊這不跟走廊潑水節一樣麽
#include<cstdio> #include<cctype> #include<algorithm> #define N 100005 #define int long long #define min(A,B) ((A)<(B)?(A):(B)) #define max(A,B) ((A)>(B)?(A):(B)) #defineView Codeswap(A,B) ((A)^=(B)^=(A)^=(B)) int val[N]; int father[N]; int d[N],fa[N]; int n,m,cnt,tot; int cme[N],fs[N]; int sze[N],son[N]; int dfn[N],top[N]; int head[N],mn[N<<2]; struct Edge{ int to,nxt,dis; }edge[N<<1]; void add(int x,int y,int z){ edge[++cnt].to=y; edge[cnt].nxt=head[x]; edge[cnt].dis=z; head[x]=cnt; } struct Node{ int x,y,dis; friend bool operator<(Node a,Node b){ return a.dis>b.dis; } }node[N*10]; int getint(){ int x=0,f=0;char ch=getchar(); while(!isdigit(ch)) f|=ch==‘-‘,ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return f?-x:x; } int find(int x){ if(father[x]==x) return x; return father[x]=find(father[x]); } void file(){ freopen("zoo.in","r",stdin); freopen("zoo.out","w",stdout); } signed main(){ file(); n=getint(),m=getint(); for(int i=1;i<=n;i++){ father[i]=i; sze[i]=1; val[i]=getint(); } for(int i=1;i<=m;i++){ node[i].x=getint(); node[i].y=getint(); node[i].dis=min(val[node[i].x],val[node[i].y]); } int now=0; std::sort(node+1,node+1+m); for(int i=1;i<=m;i++){ int x=find(node[i].x); int y=find(node[i].y); if(x==y) continue; father[x]=y; now+=sze[x]*sze[y]*node[i].dis; sze[y]+=sze[x]; } printf("%lld\n",now<<1); return 0; }
T2 可以開兩個樹狀數組分別存每個點之前線段左、右端點各出現了多少次。
然後查詢就是用右端點之前出現了多少次減去左端點減一之前出現了多少次
#include<cstdio> #include<cctype> #include<cstring> #include<algorithm> #define N 200005 #define min(A,B) ((A)<(B)?(A):(B)) #define max(A,B) ((A)>(B)?(A):(B)) #define swap(A,B) ((A)^=(B)^=(A)^=(B)) int tot,cnt; int g[N<<1]; int l[N],r[N]; int T,n,cas,m; int ques[N][5]; int xgl[N],xgr[N]; struct BIT{ int f[N<<1]; void clear(){ memset(f,0,sizeof f); } int query(int x){ int ans=0; for(;x>=1;x-=x&-x) ans+=f[x]; return ans; } void add(int x,int y){ for(;x<=m;x+=x&-x) f[x]+=y; } }a,b; int getint(){ int x=0,f=0;char ch=getchar(); while(!isdigit(ch)) f|=ch==‘-‘,ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return f?-x:x; } signed main(){ freopen("segment.in","r",stdin); freopen("segment.out","w",stdout); T=getint(); while(T--){ a.clear();b.clear(); cnt=tot=0; n=getint(); for(int i=1;i<=n;i++){ ques[i][1]=getint(); ques[i][2]=getint(); if(ques[i][1]){ xgl[i]=l[ques[i][2]]; xgr[i]=r[ques[i][2]]; } else{ cnt++; ques[i][3]=ques[i][2]+cnt; l[cnt]=ques[i][2]; r[cnt]=ques[i][3]; g[++tot]=ques[i][2]; g[++tot]=ques[i][3]; } } std::sort(g+1,g+1+tot); m=std::unique(g+1,g+1+tot)-g-1; printf("Case #%d:\n",++cas); for(int i=1;i<=n;i++){ if(ques[i][1]==0){ ques[i][2]=std::lower_bound(g+1,g+1+m,ques[i][2])-g; ques[i][3]=std::lower_bound(g+1,g+1+m,ques[i][3])-g; printf("%d\n",b.query(ques[i][3])-a.query(ques[i][2]-1)); a.add(ques[i][2],1); b.add(ques[i][3],1); } else{ xgl[i]=std::lower_bound(g+1,g+1+m,xgl[i])-g; xgr[i]=std::lower_bound(g+1,g+1+m,xgr[i])-g; a.add(xgl[i],-1); b.add(xgr[i],-1); } } } return 0; }View Code
T3 什麽鬼啊餵 2^((n-1)*(m-1)-k) 是啥啊 noip 壓軸題靠打表的啊啊啊?
證明:不會(×)
#include<cstdio> #include<cctype> #include<cstring> #define int long long #define min(A,B) ((A)<(B)?(A):(B)) #define max(A,B) ((A)>(B)?(A):(B)) #define swap(A,B) ((A)^=(B)^=(A)^=(B)) int k; int n,m,p; int ksm(int a,int b){ int ans=1; if(b<0) return ans; while(b){ if(b&1) ans=ans*a%p; a=a*a%p; b>>=1; } return ans; } int getint(){ int x=0,f=0;char ch=getchar(); while(!isdigit(ch)) f|=ch==‘-‘,ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return f?-x:x; } signed main(){ freopen("number.in","r",stdin); freopen("number.out","w",stdout); n=getint();m=getint();k=getint(); for(int i=1;i<=k;i++) int a=getint(),b=getint(),c=getint(); p=getint(); if((n+m)%2==1) return printf("0"),0; printf("%lld\n",ksm(2,(n-1)*(m-1)-k)); return 0; }View Code
[總結] NOIP 前的考試記錄