SWERC 2019-2020 做题记录
Posted uuzhateteee
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SWERC 2019-2020 做题记录相关的知识,希望对你有一定的参考价值。
A.
就是个带限制的最短路,多开一维状态(dis(i,j))表示到点(i),走的路程是(j)的最小值
注意各种细节就行了
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct Point 4 { 5 int x,y; 6 Point(int X=0,int Y=0):x(X),y(Y){} 7 }a[1005]; 8 int dist(int u,int v) 9 { 10 return (int)(ceil(sqrt((a[u].x-a[v].x)*(a[u].x-a[v].x)+(a[u].y-a[v].y)*(a[u].y-a[v].y)))); 11 } 12 int C[105]; 13 int xs,ys,xd,yd,B,T; 14 int n; 15 vector< pair<int,int> > g[1005]; 16 int dis[1005][105]; 17 bool used[1005][105]; 18 int main() 19 { 20 scanf("%d%d%d%d%d%d%d",&xs,&ys,&xd,&yd,&B,&C[0],&T); 21 for(int i=1;i<=T;++i)scanf("%d",&C[i]); 22 scanf("%d",&n); 23 a[0].x=xs;a[0].y=ys;a[n+1].x=xd;a[n+1].y=yd; 24 for(int i=1;i<=n;++i) 25 { 26 g[0].push_back(make_pair(i,C[0])); 27 g[i].push_back(make_pair(0,C[0])); 28 g[n+1].push_back(make_pair(i,C[0])); 29 g[i].push_back(make_pair(n+1,C[0])); 30 } 31 g[0].push_back(make_pair(n+1,C[0])); 32 g[n+1].push_back(make_pair(0,C[0])); 33 for(int i=1;i<=n;++i) 34 { 35 scanf("%d%d",&a[i].x,&a[i].y); 36 int k; 37 scanf("%d",&k); 38 while(k--) 39 { 40 int j,mj; 41 scanf("%d%d",&j,&mj); 42 j++; 43 g[i].push_back(make_pair(j,C[mj])); 44 g[j].push_back(make_pair(i,C[mj])); 45 } 46 } 47 for(int u=0;u<=n+1;++u) 48 { 49 for(int i=0;i<g[u].size();++i) 50 { 51 int v=g[u][i].first,c=g[u][i].second; 52 g[u][i].second*=dist(u,v); 53 } 54 } 55 for(int i=0;i<=n+1;++i) 56 for(int j=0;j<=B;++j)dis[i][j]=1000000007; 57 priority_queue<pair<int,pair<int,int>>> q; 58 q.push(make_pair(0,make_pair(0,0))); 59 dis[0][0]=0; 60 while(!q.empty()) 61 { 62 int u=q.top().second.first,k=q.top().second.second; 63 q.pop(); 64 if(used[u][k])continue; 65 used[u][k]=1; 66 for(auto p:g[u]) 67 { 68 int v=p.first,w=p.second; 69 int d=dist(u,v); 70 if(k+d>B)continue; 71 if(dis[v][k+d]>dis[u][k]+w) 72 { 73 dis[v][k+d]=dis[u][k]+w; 74 q.push(make_pair(-dis[v][k+d],make_pair(v,k+d))); 75 } 76 } 77 } 78 int ans=1000000007; 79 for(int i=0;i<=B;++i)ans=min(ans,dis[n+1][i]); 80 if(ans<1000000007)printf("%d ",ans); 81 else puts("-1"); 82 }
B.
签到
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 char s[22]; 5 map<string,int> mp; 6 int main() 7 { 8 scanf("%d",&n); 9 bool yes=0; 10 for(int i=1;i<=n;++i) 11 { 12 scanf("%s",s); 13 mp[(string)s]++; 14 if(mp[s]>n/2) 15 { 16 yes=1; 17 printf("%s ",s); 18 break; 19 } 20 } 21 if(!yes)puts("NONE"); 22 }
C.
签到
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 int has[1000005]; 5 int main() 6 { 7 scanf("%d",&n); 8 for(int i=1;i<=n;++i) 9 { 10 int x; 11 scanf("%d",&x); 12 if(0<=x&&x<=n-1)has[x]=1; 13 } 14 for(int i=0;i<=n;++i)if(!has[i]) 15 { 16 printf("%d ",i); 17 return 0; 18 } 19 }
F.
签到
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 struct Point 5 { 6 ll x,y; 7 Point(ll x=0,ll y=0):x(x),y(y){} 8 }; 9 typedef vector<Point> Polygon; 10 typedef Point Vector; 11 Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);} 12 Vector operator - (Point A,Point B){return Vector(A.x-B.x,A.y-B.y);} 13 ll Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;} 14 ll PolygonArea(vector<Point> p) 15 { 16 int n=p.size(); 17 ll area=0; 18 for(int i=1;i<n-1;++i)area+=Cross(p[i]-p[0],p[i+1]-p[0]); 19 return abs(area); 20 } 21 int n; 22 int main() 23 { 24 scanf("%d",&n); 25 ll ans=0; 26 for(int i=1;i<=n;++i) 27 { 28 vector<Point> p; 29 p.clear(); 30 int k; 31 scanf("%d",&k); 32 while(k--) 33 { 34 Point a; 35 scanf("%I64d%I64d",&a.x,&a.y); 36 p.push_back(a); 37 } 38 ans+=PolygonArea(p); 39 } 40 printf("%I64d ",ans/2); 41 }
I.签到
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a,b,c; 4 int main(){ 5 scanf("%d%d%d",&a,&b,&c); 6 int ans=(a+1)*(b+1)/(c+1)-1; 7 printf("%d ",ans); 8 }
J.
考虑在区间([l,r])中,如果有几个高度相同的最小高度的点,那以这几个为分界点把区间划开,剩下区间递归下去做,这几个点用卡特兰数算一下就行
然后我们考虑怎么找最小高度的点
每个点记录一个(next[i])表示和(a[i])高度相同的下一个位置
第一个点可以通过ST表找到,剩下点直接跳就行了
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int mod = 1000000007; 4 int n; 5 int a[1000005],nxt[1000005]; 6 vector<int> h[1000005]; 7 int st[1000005][21]; 8 int fac[2000005],inv[2000005]; 9 int fastpow(int a,int p) 10 { 11 int ans=1; 12 for(;p;p>>=1,a=1ll*a*a%mod)if(p&1)ans=1ll*ans*a%mod; 13 return ans; 14 } 15 int C(int x,int y) 16 { 17 return 1ll*fac[x]*inv[y]%mod*inv[x-y]%mod; 18 } 19 int Catalan(int x) 20 { 21 return 1ll*C(2*x,x)*fastpow(x+1,mod-2)%mod; 22 } 23 int query(int l,int r) 24 { 25 int k=log2(r-l+1); 26 if(a[st[l][k]]<=a[st[r-(1<<k)+1][k]])return st[l][k]; 27 else return st[r-(1<<k)+1][k]; 28 } 29 int solve(int l,int r) 30 { 31 if(l>=r)return 1; 32 int ans=1,cnt=1; 33 int i=query(l,r); 34 ans=1ll*ans*solve(l,i-1)%mod; 35 while(1) 36 { 37 if(nxt[i]<=r) 38 { 39 ans=1ll*ans*solve(i+1,nxt[i]-1)%mod; 40 cnt++; 41 i=nxt[i]; 42 } 43 else 44 { 45 ans=1ll*ans*solve(i+1,r)%mod; 46 break; 47 } 48 } 49 ans=1ll*ans*Catalan(cnt)%mod; 50 return ans; 51 } 52 int main() 53 { 54 fac[0]=inv[0]=1; 55 for(int i=1;i<=2000000;++i)fac[i]=1ll*fac[i-1]*i%mod; 56 for(int i=1;i<=2000000;++i)inv[i]=fastpow(fac[i],mod-2); 57 scanf("%d",&n); 58 for(int i=1;i<=n;++i) 59 { 60 scanf("%d",&a[i]); 61 h[a[i]].push_back(i); 62 } 63 for(int i=0;i<=1000000;++i)h[i].push_back(n+1); 64 for(int i=0;i<=1000000;++i) 65 for(int j=0;j<h[i].size()-1;++j)nxt[h[i][j]]=h[i][j+1]; 66 for(int i=1;i<=n;++i)st[i][0]=i; 67 for(int j=1;(1<<j)<=n;++j) 68 for(int i=1;i+(1<<j)-1<=n;++i) 69 { 70 if(a[st[i][j-1]]<=a[st[i+(1<<(j-1))][j-1]])st[i][j]=st[i][j-1]; 71 else st[i][j]=st[i+(1<<(j-1))][j-1]; 72 } 73 printf("%d ",solve(1,n)); 74 }
K.
反向建图,考虑不直接连边时T点到所有相连点的可达性,因为若不通过直接连接的边,一定会通过另一与T直接相连的点
考虑对所有直接连接T的点二进制分组,一组连边一组不连,每次未连接的点若可达,则不满足题目要求
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 int n,m,t,vis[N],first[N],tot,cnt,ans[N],ansnum,flag[N]; 5 struct edge{ 6 int to,next,num; 7 }e[N*2]; 8 void add(int u,int v){ 9 e[++tot].next=first[u],first[u]=tot; 10 e[tot].to=v; 11 } 12 void bfs(int x,int tp){ 13 queue<int>q; 14 for(int i=first[t];i;i=e[i].next){ 15 if((e[i].num&(1<<x))==(tp<<x)){ 16 int u=e[i].to; 17 vis[u]=1;q.push(u); 18 } 19 } 20 while(!q.empty()){ 21 int now=q.front();q.pop(); 22 for(int i=first[now];i;i=e[i].next){ 23 int u=e[i].to; 24 if(vis[u]||u==t)continue; 25 vis[u]=1;q.push(u); 26 } 27 } 28 } 29 int main(){ 30 scanf("%d%d%d",&n,&m,&t); 31 for(int i=1,u,v;i<=m;i++){ 32 scanf("%d%d",&u,&v); 33 add(v,u); 34 if(v==t){ 35 e[tot].num=cnt++;flag[u]=1; 36 } 37 } 38 for(int i=0;(1<<i)<=cnt*4;i++){ 39 memset(vis,0,sizeof(vis)); 40 bfs(i,1); 41 for(int j=first[t];j;j=e[j].next){ 42 int u=e[j].to; 43 if(vis[u]&&(e[j].num&(1<<i))==0){ 44 if(!ans[u])ans[u]=1,ansnum++; 45 } 46 } 47 memset(vis,0,sizeof(vis)); 48 bfs(i,0); 49 for(int j=first[t];j;j=e[j].next){ 50 int u=e[j].to; 51 if(vis[u]&&(e[j].num&(1<<i))){ 52 if(!ans[u])ans[u]=1,ansnum++; 53 } 54 } 55 } 56 printf("%d ",cnt-ansnum); 57 for(int i=0;i<n;i++) 58 if(!ans[i]&&flag[i])printf("%d ",i); 59 }
L.
我们把和每个湿地相连的连通块抠出来,这样的每个连通块大小不会超过(2n)
然后又因为每个这样的连通块是独立的,因此单独求SG最后异或一下就行了
求SG就状压一下然后记忆化搜索,注意判掉不合法的情况
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 char a[12][12]; 5 bool vis[12][12]; 6 int bel[12][12],now; 7 struct Point 8 { 9 int x,y; 10 }pos[22]; 11 int cnt; 12 void dfs(int i,int j,int k) 13 { 14 if(vis[i][j])return; 15 if(a[i][j]!=‘.‘)return; 16 if(a[i-1][j]!=‘*‘&&a[i+1][j]!=‘*‘&&a[i][j-1]!=‘*‘&&a[i][j+1]!=‘*‘)return; 17 if(bel[i][j]!=k)return; 18 pos[cnt].x=i;pos[cnt].y=j; 19 cnt++; 20 vis[i][j]=1; 21 dfs(i-1,j,k);dfs(i+1,j,k);dfs(i,j-1,k);dfs(i,j+1,k); 22 } 23 bool va(int S) 24 { 25 for(int i=0;i<cnt;++i)if(S&(1<<i)) 26 for(int j=i+1;j<cnt;++j)if(S&(1<<j)) 27 { 28 if(pos[i].x==pos[j].x) 29 { 30 if(pos[i].y==pos[j].y-1) 31 { 32 if(bel[pos[i].x][pos[i].y]==bel[pos[j].x][pos[j].y])return 0; 33 } 34 if(pos[i].y==pos[j].y+1) 35 { 36 if(bel[pos[i].x][pos[i].y]==bel[pos[j].x][pos[j].y])return 0; 37 } 38 } 39 else if(pos[i].y==pos[j].y) 40 { 41 if(pos[i].x==pos[j].x-1) 42 { 43 if(bel[pos[i].x][pos[i].y]==bel[pos[j].x][pos[j].y])return 0; 44 } 45 if(pos[i].x==pos[j].x+1) 46 { 47 if(bel[pos[i].x][pos[i].y]==bel[pos[j].x][pos[j].y])return 0; 48 } 49 } 50 } 51 return 1; 52 } 53 int sg[1050000],has[1050000]; 54 int getsg(int S) 55 { 56 if(has[S])return sg[S]; 57 has[S]=1; 58 int nxt[22]; 59 memset(nxt,0,sizeof(nxt)); 60 for(int i=0;i<cnt;++i)if(!(S&(1<<i))) 61 { 62 int sta=(S|(1<<i)); 63 if(va(sta)) 64 { 65 int k=getsg(sta); 66 nxt[k]=1; 67 } 68 } 69 for(int i=0;i<=cnt;++i)if(!nxt[i]) 70 { 71 sg[S]=i; 72 break; 73 } 74 return sg[S]; 75 } 76 int solve() 77 { 78 memset(has,0,sizeof(has)); 79 memset(sg,0,sizeof(sg)); 80 getsg(0); 81 return sg[0]; 82 } 83 const int dx[]={-1,0,1,0}; 84 const int dy[]={0,-1,0,1}; 85 int main() 86 { 87 scanf("%d",&n); 88 for(int i=1;i<=n;++i)scanf("%s",a[i]+1); 89 int ans=0; 90 for(int i=1;i<=n;++i) 91 for(int j=1;j<=n;++j)if(a[i][j]==‘*‘&&(!bel[i][j])) 92 { 93 bel[i][j]=++now; 94 queue< pair<int,int> > q; 95 q.push(make_pair(i,j)); 96 while(!q.empty()) 97 { 98 int x=q.front().first,y=q.front().second; 99 q.pop(); 100 for(int i=0;i<4;++i) 101 { 102 int nx=x+dx[i],ny=y+dy[i]; 103 if(bel[nx][ny])continue; 104 bel[nx][ny]=now; 105 if(a[nx][ny]==‘*‘)q.push(make_pair(nx,ny)); 106 } 107 } 108 } 109 for(int i=1;i<=n;++i) 110 for(int j=1;j<=n;++j)if(a[i][j]==‘.‘&&(a[i-1][j]==‘*‘||a[i+1][j]==‘*‘||a[i][j-1]==‘*‘||a[i][j+1]==‘*‘)&&(!vis[i][j])) 111 { 112 cnt=0; 113 dfs(i,j,bel[i][j]); 114 ans^=solve(); 115 } 116 if(ans)puts("First player will win"); 117 else puts("Second player will win"); 118 }
以上是关于SWERC 2019-2020 做题记录的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 4439: [Swerc2015]Landscaping -- 最小割
计算几何多边形面积——swerc Gym - 102501F