day2018.11.7模擬賽總結
今天的模擬賽打完就可以開始頹到NOIP2018前一個小時了...
T1:
題目大意:給你一個五子棋的下棋序列,讓你判定在什麼時候結束,誰贏了.
考場得分:100.
每一次處理的時候判定一下就可以了十分容易.
程式碼如下:
#include<bits/stdc++.h> using namespace std; #define Abigail inline void typedef long long LL; const int N=15; int a[N+9][N+9],n; bool check(int x,int y){ //判定是否決出勝負 int sum=1; for (int i=x-1;a[i][y]==a[x][y];--i) ++sum; for (int i=x+1;a[i][y]==a[x][y];++i) ++sum; if (sum>=5) return 1; //行 sum=1; for (int j=y-1;a[x][j]==a[x][y];--j) ++sum; for (int j=y+1;a[x][j]==a[x][y];++j) ++sum; if (sum>=5) return 1; //列 sum=1; for (int i=x-1,j=y-1;a[i][j]==a[x][y];--i,--j) ++sum; for (int i=x+1,j=y+1;a[i][j]==a[x][y];++i,++j) ++sum; if (sum>=5) return 1; //x-y相等的對角線 sum=1; for (int i=x-1,j=y+1;a[i][j]==a[x][y];--i,++j) ++sum; for (int i=x+1,j=y-1;a[i][j]==a[x][y];++i,--j) ++sum; if (sum>=5) return 1; //x+y相等的對角線 return 0; } Abigail getans(){ scanf("%d",&n); int x,y; for (int i=1;i<=n;++i){ scanf("%d%d",&x,&y); a[x][y]=i&1?1:2; if (check(x,y)){ i&1?printf("A %d\n",i):printf("B %d\n",i); break; } x=y=0; } if (!x) puts("Tie"); } int main(){ freopen("five.in","r",stdin); freopen("five.out","w",stdout); getans(); return 0; }
T2:
題目大意:給定一張無向圖,以及k個終點.現在要從點0走到這k個終點,且在當前點會有隨機的d條以當前點為一端的邊不能走,求在最壞情況下的最短路.
考場得分:75.
考場看到這道圖論題就感覺比較容易,應該可以拿個高分,然後開始磕.先考慮了若是DAG上的情況,發現從終點開始反著DP即可.然後考慮無向圖上,就把DP換成最短路就可以開心的AC這道題了.
然後發現這道題直接寫堆優化dijkstra貌似是錯誤的,貌似必須要用SPFA的多次迭代才能完成,然後就寫了一個時間複雜度上限但實際跑得飛快的SPFA,拿到了75分的高分.
實際上正解是一個被魔改了的dijkstra.我們考慮這道題與普通最短路的區別,發現只是多了一個取d+1短的條件.那麼考慮給每一個點維護一個大小不超過d+1的大根堆,存所有dis值已經確定的與這個點相鄰的dis值,那麼每次更新一個值取堆頂即可.
75分SPFA程式碼如下:
#include<bits/stdc++.h> using namespace std; #define Abigail inline void typedef long long LL; const int N=100000,M=1000000; const LL INF=(1LL<<60)-1; struct side{ int y,next; LL v; }e[M*2+9]; int lin[N+9],top=1; int fr[N+9],k,n,m,d; void ins(int x,int y,LL v){ e[++top].y=y;e[top].v=v; e[top].next=lin[x]; lin[x]=top; } int use[N+9],tt; LL dis[N+9],tmp[N+9]; queue<int>q; void SPFA(){ for (int i=1;i<=n;++i) dis[i]=INF; for (int i=1;i<=k;++i){ dis[fr[i]]=0; use[fr[i]]=1; q.push(fr[i]); } while (!q.empty()){ int t=q.front();q.pop(); use[t]=0; for (int i=lin[t];i;i=e[i].next){ tt=0; for (int j=lin[e[i].y];j;j=e[j].next) tmp[++tt]=dis[e[j].y]+e[j].v; if (d>=tt) continue; nth_element(tmp+1,tmp+d+1,tmp+tt+1); if (tmp[d+1]<dis[e[i].y]){ dis[e[i].y]=tmp[d+1]; if (use[e[i].y]) continue; use[e[i].y]=1; q.push(e[i].y); } } } } Abigail into(){ scanf("%d%d%d%d",&n,&m,&k,&d); int x,y;LL v; for (int i=1;i<=m;++i){ scanf("%d%d%lld",&x,&y,&v); ++x;++y; ins(x,y,v);ins(y,x,v); } for (int i=1;i<=k;++i) { scanf("%d",&fr[i]); ++fr[i]; } } Abigail work(){ SPFA(); } Abigail outo(){ printf("%lld\n",dis[1]==INF?-1:dis[1]); } int main(){ freopen("maze.in","r",stdin); freopen("maze.out","w",stdout); into(); work(); outo(); return 0; }
100分堆優化dijkstra程式碼如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=100000,M=1000000;
const LL INF=(1LL<<60)-1;
struct side{
int y,next;
LL v;
}e[M*2+9];
int lin[N+9],top=1;
int fr[N+9],k,n,m,D;
void ins(int x,int y,LL v){
e[++top].y=y;e[top].v=v;
e[top].next=lin[x];
lin[x]=top;
}
int use[N+9];
LL dis[N+9];
struct node{
int x;
LL v;
node(){}
node(int X,int V){x=X;v=V;}
bool operator > (const node &p)const{return v>p.v;}
};
priority_queue<node,vector<node>,greater<node> >q;
priority_queue<LL>d[N+9];
void dijkstra(){
for (int i=1;i<=n;++i) dis[i]=INF;
for (int i=1;i<=k;++i){
dis[fr[i]]=0;
q.push(node(fr[i],0LL));
}
while (!q.empty()){
int t=q.top().x;q.pop();
if (use[t]) continue;
use[t]=1;
for (int i=lin[t];i;i=e[i].next){
d[e[i].y].push(dis[t]+e[i].v);
if (d[e[i].y].size()>D+1) d[e[i].y].pop();
if (d[e[i].y].size()==D+1&&d[e[i].y].top()<dis[e[i].y]){
dis[e[i].y]=d[e[i].y].top();
q.push(node(e[i].y,dis[e[i].y]));
}
}
}
}
Abigail into(){
scanf("%d%d%d%d",&n,&m,&k,&D);
int x,y;LL v;
for (int i=1;i<=m;++i){
scanf("%d%d%lld",&x,&y,&v);
++x;++y;
ins(x,y,v);ins(y,x,v);
}
for (int i=1;i<=k;++i) {
scanf("%d",&fr[i]);
++fr[i];
}
}
Abigail work(){
dijkstra();
}
Abigail outo(){
printf("%lld\n",dis[1]==INF?-1:dis[1]);
}
int main(){
freopen("maze.in","r",stdin);
freopen("maze.out","w",stdout);
into();
work();
outo();
return 0;
}
T3:
題目大意:給定一個序列A以及一個常數k,並定義一個子段的平均值為:
現在要求這個序列的平均值最大的長度在的子段的平均值.
考場得分:50.
考場發現自己只會暴力,然後用線段樹優化了一波,時間複雜度為.
正解先提出了一個性質,若沒有長度限制的話,那麼最大平均值子段的最大值和最小值一定為這個子段的兩端.
有了這個性質,我們就可以愉快地將平均值的式子寫成:
突然優美了許多,我們只需要再設a陣列為A陣列的差分陣列,就可以將式子寫成:
那麼考慮二分ans,然後就可以得出,若這個上式大於ans,則ans一定偏小.
那麼維護一下這個式子就可以了,時間複雜度.
程式碼太神了不敢寫了.(其實是太懶了)