A. Passage

枚举两个点,看看删掉之后剩下的图是否是二分图。

#include <bits/stdc++.h>
using namespace std ; const int MAXN = 205 ; vector < int > G[MAXN] ;
int vis[MAXN] , col[MAXN] ;
int n ; int dfs ( int u ) {
for ( int i = 0 ; i < G[u].size () ; ++ i ) {
int v = G[u][i] ;
if ( vis[v] == 0 ) continue ;
if ( !col[v] ) {
col[v] = 3 - col[u] ;
if ( !dfs ( v ) ) return 0 ;
}
if ( col[u] + col[v] != 3 ) return 0 ;
}
return 1 ;
} int check () {
for ( int i = 1 ; i <= n ; ++ i ) {
col[i] = 0 ;
}
for ( int i = 1 ; i <= n ; ++ i ) {
if ( col[i] || !vis[i] ) continue ;
col[i] = 1 ;
if ( !dfs ( i ) ) return 0 ;
}
return 1 ;
} void solve () {
for ( int i = 1 ; i <= n ; ++ i ) {
int x , y ;
scanf ( "%d" , &x ) ;
for ( int j = 0 ; j < x ; ++ j ) {
scanf ( "%d" , &y ) ;
G[i].push_back ( y ) ;
G[y].push_back ( i ) ;
}
vis[i] = 1 ;
}
if ( n <= 3 ) {
printf ( "Hurrah!\n" ) ;
return ;
}
for ( int i = 1 ; i <= n ; ++ i ) {
for ( int j = i + 1 ; j <= n ; ++ j ) {
vis[i] = vis[j] = 0 ;
if ( check () ) {
printf ( "Hurrah!\n" ) ;
return ;
}
vis[i] = vis[j] = 1 ;
}
}
printf ( "Fired.\n" ) ;
} int main () {
freopen ( "input.txt" , "r" , stdin ) ;
freopen ( "output.txt" , "w" , stdout ) ;
while ( ~scanf ( "%d" , &n ) ) solve () ;
return 0 ;
}

  

B. Files list

按题意模拟。

#include <bits/stdc++.h>
using namespace std ; const int MAXN = 10005 ; map < string , int > mp ;
map < int , string > mp2 ;
char s[MAXN] , p[MAXN] ;
int n ; void solve () {
mp.clear () ;
mp2.clear () ;
int cnt = 0 ;
for ( int i = 0 ; i < n ; ++ i ) {
scanf ( "%s" , s ) ;
int t = 0 , f = 0 ;
for ( int j = 0 ; s[j] ; ++ j ) {
if ( f ) p[t ++] = s[j] ;
else if ( s[j] == '.' ) f = 1 ;
}
p[t] = 0 ;
if ( mp.count ( p ) ) mp[p] ++ ;
else {
mp[p] ++ ;
mp2[++ cnt] = p ;
}
}
for ( int i = 1 ; i <= cnt ; ++ i ) {
cout << mp2[i] << ": " << mp[mp2[i]] << endl ;
}
} int main () {
freopen ( "input.txt" , "r" , stdin ) ;
freopen ( "output.txt" , "w" , stdout ) ;
while ( ~scanf ( "%d" , &n ) ) solve () ;
return 0 ;
}

  

C. Graph optimization

将所有1类限制的边加入,分块bitset判定限制2是否都满足即可。

时间复杂度$O(\frac{nm}{64})$。

#include<algorithm>
#include<cstdio>
#include<bitset>
#include<set>
#include<ctime>
using namespace std;
typedef bitset<4096>B;
typedef unsigned long long ll;
const int N=300010; int n,m,i,j,k,x,y,z,ans[N][2],quailty;
int g[N],G[N],v[N],nxt[N],ed; int vis[N],q[N],h,t,cnt,f[N],d[N];
B dp[100010];//dp[x] : this can reach x set<int>SET[100010]; struct E{int x,y,z;}e[N]; const int BUF=5000000;
char Buf[BUF],*buf=Buf;
inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;} inline bool cmp(const E&a,const E&b){return a.z<b.z;}
inline void add(int x,int y){
v[++ed]=y;nxt[ed]=g[x];g[x]=ed;
}
inline void add2(int x,int y){
v[++ed]=y;nxt[ed]=G[x];G[x]=ed;
}
void dfs1(int x){
vis[x]=1;
for(int i=g[x];i;i=nxt[i])if(!vis[v[i]])dfs1(v[i]);
q[++t]=x;
}
void dfs2(int x,int y){
vis[x]=0;f[x]=y;
for(int i=G[x];i;i=nxt[i])if(vis[v[i]])dfs2(v[i],y);
}
inline bool solve(int L,int R){
if ( clock () > 2.95 * CLOCKS_PER_SEC ) return 1 ;
int z=e[L].z;
int i;
for(i=1;i<=cnt;i++){
dp[i].reset();
//if ( clock () > 2.95 * CLOCKS_PER_SEC ) return 1 ;
}
for(i=max(z<<12,1);(i>>12)==z;i++){
dp[f[i]][i&4095]=1;
}
for(i=1;i<=cnt;i++){
int x=q[i];
for(int j=g[x];j;j=nxt[j]){
dp[v[j]]|=dp[x];
//if ( clock () > 2.95 * CLOCKS_PER_SEC ) return 1 ;
}
}
for(i=L;i<=R;i++){
int x=e[i].x,y=e[i].y;
//printf("-> %d %d %d %llu\n",x,y,z,dp[f[y]]);
if(dp[f[y]][x&4095])return 0;
}
return 1;
}
int main (){
freopen ( "input.txt" , "r" , stdin ) ;
freopen ( "output.txt" , "w" , stdout ) ;
fread(Buf,1,BUF,stdin);
read(n),read(m);
for(i=1;i<=m;i++){
//x=i,y=i+1;
read(x),read(y);
ans[i][0]=x,ans[i][1]=y;
add(x,y);
add2(y,x);
} for(i=1;i<=n;i++)if(!vis[i])dfs1(i);
for(i=n;i;i--)if(vis[q[i]])dfs2(q[i],++cnt); for(ed=0,i=1;i<=cnt;i++)g[i]=0;
for(i=1;i<=m;i++){
x=ans[i][0],y=ans[i][1];
if(f[x]==f[y])continue;
if(SET[f[x]].find(f[y])!=SET[f[x]].end())continue;
SET[f[x]].insert(f[y]);
add(f[x],f[y]);
d[f[y]]++;
}
for(h=1,t=0,i=1;i<=cnt;i++)if(!d[i])q[++t]=i;
while(h<=t)for(i=g[q[h++]];i;i=nxt[i])if(!(--d[v[i]]))q[++t]=v[i];
//now q is topo sequence of SCC read(quailty);
for(i=1;i<=quailty;i++){
//e[i].x=i+1;
//e[i].y=i;
read(e[i].x),read(e[i].y);
e[i].z=e[i].x>>12;
}
sort(e+1,e+quailty+1,cmp);
for(i=1;i<=quailty;i=j){
for(j=i;j<=quailty&&e[i].z==e[j].z;j++);
if(!solve(i,j-1))return puts("NO"),0;
}
puts("YES");
printf("%d\n",m);
for(i=1;i<=m;i++)printf("%d %d\n",ans[i][0],ans[i][1]);
return 0 ;
}

  

D. Housing payments

设$f[i]$表示前$i$个月付清,且第$i$个月进行了交易的最小代价,那么因为债务指数级增长,所以可用决策只有$O(\log n)$项。

#include <bits/stdc++.h>
using namespace std ; typedef pair < int , int > pii ; const int MAXN = 100005 ;
const int INF = 0x3f3f3f3f ; int s[MAXN] , x[MAXN] , p[MAXN] ;
double dp[MAXN] ;
int n ; void solve () {
for ( int i = 1 ; i <= n ; ++ i ) {
scanf ( "%d%d%d" , &s[i] , &x[i] , &p[i] ) ;
dp[i] = 1e18 ;
}
dp[0] = 0 ;
for ( int i = 0 ; i <= n ; ++ i ) {
double sum1 = 0 ;
for ( int j = i + 1 ; j <= i + 100 && j <= n ; ++ j ) {
dp[j] = min ( dp[j] , dp[i] + sum1 + s[j] + x[j] ) ;
sum1 = ( sum1 + s[j] ) * ( 1 + 0.01 * p[j] ) ;
}
}
printf ( "%.10f\n" , dp[n] ) ;
} int main () {
freopen ( "input.txt" , "r" , stdin ) ;
freopen ( "output.txt" , "w" , stdout ) ;
while ( ~scanf ( "%d" , &n ) ) solve () ;
return 0 ;
}

  

E. Arithmetic expressions

$f[i][j]$表示长度为$i$的值为$j$的表达式个数,然后枚举后面接上什么转移即可。

#include <bits/stdc++.h>
using namespace std ;
const int mod=1e9+7;
int n,m,p;
int dp[55][222];
int len[333];
void up(int &x,int y){x+=y;if(x>=mod)x-=mod;}
int main () {
freopen ( "input.txt" , "r" , stdin ) ;
freopen ( "output.txt" , "w" , stdout ) ;
while(scanf("%d%d%d",&n,&m,&p)!=EOF){
memset(dp,0,sizeof dp);
for(int i=0;i<m;i++){
int x=i;
if(!x){len[i]=1;continue;}
int l=0;
while(x)l++,x/=10;
len[i]=l;
}
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
if(len[j]==i)up(dp[i][j],1);
if(i>=3)up(dp[i][j],dp[i-2][j]);
}
//if(i==2)up(dp[i][0],1);
for(int j=0;j<m;j++){
for(int k=1;k+1<i;k++){
int nj,ni=i-k-1;
for(int nm=0;nm<m;nm++){
for(int ty=0;ty<2;ty++){
if(!ty)nj=(j+nm)%m;
else nj=(j-nm+m)%m;
if(ni>2)up(dp[i][nj],1LL*dp[k][j]*dp[ni-2][nm]%mod);
if(len[nm]==ni)up(dp[i][nj],dp[k][j]);
}
}
}
}
}
printf("%d\n",dp[n][p]);
}
return 0;
}

  

F. Sputnik

留坑。

G. Voting

设$f[i][j]$表示$i$的子树里选举情况为$j$的最小代价,转移则用另一个$dp[i][a][b][c]$表示考虑了前$i$个儿子,三个人选票各自为$a,b,c$的最小代价来转移。

#include <bits/stdc++.h>
using namespace std ;
const int mod=1e9+7;
const int Maxn=10050,M=10,Inf=1e9;
typedef pair<int,int>pi;
int n,m,K;
vector<int>G[Maxn];
int f[Maxn][4];
int g[23][23][23][23];
int ori[Maxn];
vector<pi>ans;
vector<pi>res[Maxn][4];
pi pre[23][23][23][23];
void init(int cs){
for(int i=0;i<21;i++){
for(int j=0;j<21;j++){
for(int k=0;k<21;k++)
g[cs][i][j][k]=Inf;
}
}
}
struct State{
int x,y,z;
State(){}
State(int x,int y,int z):x(x),y(y),z(z){}
}st[Maxn][4];
int get(int a,int b,int c){
vector<pi>v;
v.push_back(pi(a,1));
v.push_back(pi(b,2));
v.push_back(pi(c,3));
sort(v.begin(),v.end());
reverse(v.begin(),v.end());
if(v[0].first==v[1].first)return 0;
return v[0].second;
}
void dfs(int u){
if(u>m){
for(int i=0;i<4;i++){
if(i>K)f[u][i]=Inf;
else {
res[u][i].push_back(pi(u,i));
f[u][i]=i==ori[u]?0:1;
}
}
return ;
}
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
dfs(v);
}
int n=G[u].size();
init(0);
g[0][0][0][0]=0;
for(int i=0;i<n;i++){
int v=G[u][i];
init(i+1);
int it[4];
for(it[0]=0;it[0]<=20;it[0]++)
for(it[1]=0;it[1]<=20;it[1]++)
for(it[2]=0;it[2]<=20;it[2]++){
if(g[i][it[0]][it[1]][it[2]]==Inf)continue;
int w=g[i][it[0]][it[1]][it[2]];
for(int ty=0;ty<4;ty++){
if(f[v][ty]==Inf)continue;
if(ty)it[ty-1]++;
int nw=w+f[v][ty];
int &t=g[i+1][it[0]][it[1]][it[2]];
if(nw<t){
t=nw;
pre[i+1][it[0]][it[1]][it[2]]=pi(v,ty);
}
if(ty)it[ty-1]--;
}
}
}
for(int i=0;i<4;i++)f[u][i]=Inf;
for(int i=0;i<=20;i++){
for(int j=0;j<=20;j++){
for(int k=0;k<=20;k++){
if(g[n][i][j][k]==Inf)continue;
int ty=get(i,j,k);
if(f[u][ty]>g[n][i][j][k]){
f[u][ty]=g[n][i][j][k];
st[u][ty]=State(i,j,k);
}
}
}
}
for(int i=0;i<4;i++){
if(f[u][i]==Inf)continue;
res[u][i].clear();
State tmp=st[u][i];
for(int cur=n;cur>=1;cur--){
res[u][i].push_back(pre[cur][tmp.x][tmp.y][tmp.z]);
int ty=pre[cur][tmp.x][tmp.y][tmp.z].second;
if(ty==1)tmp.x--;
if(ty==2)tmp.y--;
if(ty==3)tmp.z--;
}
reverse(res[u][i].begin(),res[u][i].end());
}
//printf("u=%d\n",u);
//for(int i=0;i<4;i++)printf("%d ",f[u][i]);puts("");
}
void dfs2(int u,int ty){
//printf("u=%d ty=%d\n",u,ty);
if(u>m){
if(ori[u]!=ty)ans.push_back(pi(u,ty));
return;
}
//printf("sz=%d\n",(int)res[u][1].size());
for(int i=0;i<G[u].size();i++){
//printf("v=%d\n",G[u][i]);
dfs2(G[u][i],res[u][ty][i].second);
}
}
int main () {
freopen ( "input.txt" , "r" , stdin ) ;
freopen ( "output.txt" , "w" , stdout ) ;
scanf("%d%d%d",&n,&m,&K);
for(int i=1;i<=n;i++)scanf("%d",&ori[i+m]);
for(int i=1;i<=m;i++){
int k;scanf("%d",&k);
for(int j=0;j<k;j++){
int x;scanf("%d",&x);
if(x<0)x=-x;
else x=m+x;
G[i].push_back(x);
}
}
dfs(1);
//puts("ok1");
dfs2(1,1);
printf("%d\n",(int)ans.size());
for(int i=0;i<ans.size();i++)printf("%d %d\n",ans[i].first-m,ans[i].second);
return 0;
}

  

H. Novice urbanist

枚举每个点和每个区间,那么它能贡献的距离是一段区间,差分前缀和即可。

#include <bits/stdc++.h>
using namespace std ; int n,m,l,r,cnt,i,j;
int a[11111],f[4444444];
struct P{int l,r;P(){}P(int _l,int _r){l=_l,r=_r;}}b[1111],c[1111];
inline bool cmp(const P&a,const P&b){return a.l<b.l;} int main () {
freopen ( "input.txt" , "r" , stdin ) ;
freopen ( "output.txt" , "w" , stdout ) ;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=1;i<=m;i++)scanf("%d%d",&b[i].l,&b[i].r);
sort(b+1,b+m+1,cmp);
l=1e9;
r=-l;
for(i=1;i<=m;i++){
if(b[i].l>r+1){
if(l<=r)c[++cnt]=P(l,r);
l=b[i].l;
}
r=max(r,b[i].r);
}
if(l<=r)c[++cnt]=P(l,r);
for(i=1;i<=n;i++){
for(j=1;j<=cnt;j++){
f[c[j].l-a[i]+2000000]++;
f[c[j].r-a[i]+2000000+1]--;
}
}
for(i=1;i<4000000;i++)f[i]+=f[i-1];
int ans=-1,ans2;
for(i=0;i<2000000;i++){
int t=max(f[2000000+i],f[2000000-i]);
if(t>ans)ans=t,ans2=i;
}
printf("%d %d",ans2,ans);
return 0 ;
}

  

I. Rangefinder

留坑。

J. Hive

求出方向向量$(x,y)$,顺时针旋转$60$°后是$(x+y,-x)$。

#include <bits/stdc++.h>
using namespace std ;
const int Maxn=100020;
int n,x,y,a,b;
int main () {
freopen ( "input.txt" , "r" , stdin ) ;
freopen ( "output.txt" , "w" , stdout ) ;
scanf("%d%d%d",&n,&x,&y);
while(n--){
scanf("%d%d",&a,&b);
a-=x,b-=y;
printf("%d %d\n",x+a+b,y-a);
}
return 0;
}

  

K. Side effects

每次加入一条边之后暴力染色,然后将经过的边删掉,均摊复杂度$O(n+m)$。

#include <bits/stdc++.h>
using namespace std ;
const int Maxn=100020;
int n,m,q,ans;
set<int>G[Maxn];
int col[Maxn];
void dfs(int u){
//printf("u=%d\n",u);
col[u]=1;
for(set<int>::iterator it=G[u].begin();it!=G[u].end();){
//printf("iv=%d\n",*it);
if(!col[*it]){
dfs(*it);
ans++;
}
G[u].erase(it++);
}
}
void solve(){
ans=0;
for(int i=1;i<=m;i++){
int x;scanf("%d",&x);
col[x]=1;
ans++;
}
while(q--){
//puts("ok");
int u,v;scanf("%d%d",&u,&v);
if(u!=v)G[v].insert(u);
if(col[v]==1)dfs(v);
printf("%d\n",ans);
}
}
int main () {
freopen ( "input.txt" , "r" , stdin ) ;
freopen ( "output.txt" , "w" , stdout ) ;
while ( ~scanf ( "%d%d%d" , &n,&m,&q ) ) solve () ;
return 0 ;
}

  

L. Cypher

留坑。


总结:

  • 在分块bitset时,应尽量设大bitset的大小,减少bitset的操作次数,这样常数反而小。

XVI Open Cup named after E.V. Pankratiev. GP of Siberia的更多相关文章

  1. XVI Open Cup named after E.V. Pankratiev. GP of Ukraine

    A. Associated Vertices 首先求出SCC然后缩点,第一次求出每个点能到的点集,第二次收集这些点集即可,用bitset加速,时间复杂度$O(\frac{nm}{64})$. #inc ...

  2. XVI Open Cup named after E.V. Pankratiev. GP of Peterhof

    A. (a, b)-Tower 当指数大于模数的时候用欧拉定理递归计算,否则直接暴力计算. #include<cstdio> #include<algorithm> #incl ...

  3. XVI Open Cup named after E.V. Pankratiev. GP of Ekaterinburg

    A. Avengers, The 留坑. B. Black Widow 将所有数的所有约数插入set,然后求mex. #include<bits/stdc++.h> using names ...

  4. XVI Open Cup named after E.V. Pankratiev. GP of Eurasia

    A. Nanoassembly 首先用叉积判断是否在指定向量右侧,然后解出法线与给定直线的交点,再关于交点对称即可. #include<bits/stdc++.h> using names ...

  5. XVI Open Cup named after E.V. Pankratiev. GP of SPB

    A. Bubbles 枚举两个点,求出垂直平分线与$x$轴的交点,答案=交点数+1. 时间复杂度$O(n^2\log n)$. #include<cstdio> #include<a ...

  6. XVI Open Cup named after E.V. Pankratiev. GP of Ekaterinburg--I.Iron man

    n个服务器,k类任务,每个服务器完成一个任务都有特定的花费$cost_{i,j}$,但是你设置好某台机器去完成某项任务时他只能去完成这类任务,除非你可以花费$C$去更改配置.第$i$天要求去完成$q_ ...

  7. XVII Open Cup named after E.V. Pankratiev. GP of Siberia, Division 1

    1. Ski race 枚举枚举倍数判断即可.时间复杂度$O(n\log m)$. #include<cstdio> #include<algorithm> using nam ...

  8. XV Open Cup named after E.V. Pankratiev. GP of Tatarstan

    A. Survival Route 留坑. B. Dispersed parentheses $f[i][j][k]$表示长度为$i$,未匹配的左括号数为$j$,最多的未匹配左括号数为$k$的方案数. ...

  9. XVII Open Cup named after E.V. Pankratiev. GP of SPb

    A. Array Factory 将下标按前缀和排序,然后双指针,维护最大的右边界即可. #include<cstdio> #include<algorithm> using ...

随机推荐

  1. 原子类java.util.concurrent.atomic.*原理分析

    原子类java.util.concurrent.atomic.*原理分析 在并发编程下,原子操作类的应用可以说是无处不在的.为解决线程安全的读写提供了很大的便利. 原子类保证原子的两个关键的点就是:可 ...

  2. android中xml tools属性详解

    第一部分 安卓开发中,在写布局代码的时候,ide可以看到布局的预览效果. 但是有些效果则必须在运行之后才能看见,比如这种情况:TextView在xml中没有设置任何字符,而是在activity中设置了 ...

  3. iOS警告收录及科学快速的消除方法

    来自: http://www.cnblogs.com/dsxniubility/p/4757760.html iOS警告收录及科学快速的消除方法     前言:现在你维护的项目有多少警告?看着几百条警 ...

  4. git知识点整理

  5. Debian8升级4.5内核

    本文讲述如何升级Debian8的内核到4.5版本 0x01:去linux kernel官网https://www.kernel.org/下载4.5的内核,选择tar.xz格式 0x02:想办法把下载好 ...

  6. ubuntu 搞坏了sudoers文件之修复方案

    pkexec visudo askubuntu原回答摘抄如下 On a modern Ubuntu system (and many other GNU/Linux distributions), f ...

  7. Delaunay剖分与平面欧几里得距离最小生成树

    这个东西代码我是对着Trinkle的写的,所以就不放代码了.. Delaunay剖分的定义: 一个三角剖分是Delaunay的当且仅当其中的每个三角形的外接圆内部(不包括边界)都没有点. 它的存在性是 ...

  8. Springboot快速入门创建

    maven构建项目 1.访问http://start.spring.io/,进入快速创建工程的主页 可参考下图所示: 2.选择构建工具Maven Project.Spring Boot版本1.3.6以 ...

  9. LeetCode 359 Logger Rate Limiter

    Problem: Design a logger system that receive stream of messages along with its timestamps, each mess ...

  10. js方法入参或局部变量和全局变量重名,用来赋值全局变量会失败

    今天遇到个bug,最后终于知道原因了,js方法入参和全局变量重名,用入参赋值全局变量失败,就是说方法入参不能和全局变量重名. 现在下面的例子也说明,局部变量和全局变量不可以同名不光是入参,只要同名赋值 ...