zr2019暑期高端峰会AB组day4
A. 猫
link
先给距离做个前缀和,知道每座山离一号位置的距离 对于每只猫,求出
a
[
i
]
a[i]
a [ i ] 代表最晚在
a
[
i
]
a[i]
a [ i ] 时刻出发可以接到低
i
i
i 只猫 我们再按
a
[
i
]
a[i]
a [ i ] 给每只猫从小到大排序,就变成了把这些猫分成最多
p
p
p 段的问题,每次分段有相应的代价 方程是
d
p
[
i
]
=
min
{
d
p
[
j
]
+
s
[
i
]
−
s
[
j
]
+
(
i
−
j
)
∗
a
[
i
]
}
dp[i]=\min \{dp[j]+s[i]-s[j]+(i-j)*a[i]\}
d p [ i ] = min { d p [ j ] + s [ i ] − s [ j ] + ( i − j ) ∗ a [ i ] }
s
[
i
]
−
s
[
j
]
s[i]-s[j]
s [ i ] − s [ j ] 这一项可以不看,最后直接加上全长,这个式子关于
i
i
i 的和关于
j
j
j 的乘到了一起,显然可以斜率优化DP考场上数据范围算错了没开
l
o
n
g
l
o
n
g
long long
l o n g l o n g 爆了10分,90分
B. 打地鼠
link
这题20分就是01压位加个BSF 50分好像还是搜索,再加上一些特判?? 然而场上A了这题的四个人只有一个写了正解,其他的居然都是写了暴力对拍,把所有无解的情况都拍出来,大概四五种,全部判一下,否则输出1 那么正解需要我们反着考虑,对于一个在下面的地鼠,我们考虑把它拔出来,我们令下去的地鼠是黑色,上来的是白色,那么一个可以拔出来的地鼠必需满足同行同列只有这一个黑色 ,那么这行这列的其他地鼠我们给它标记灰色,代表可黑可白,最后我们再看看这个形态是否符合初始形态 由于我们每次做这个逆操作的时候都判断了这个地鼠是不是行列中唯一的黑点,所有我们只会把白点变成灰点,这些灰点又可以被当做黑点做逆操作 最后有很多灰色的交点,必需有一个是白色的,不然没法起步,其他位置对应相等即可
C. 奇怪的和
link
这是什么大力推式子数学题啊,赛后都只有两个人改出来,我是真的顶不住 果断咕之
T1考场代码
#include <bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
#define pb push_back
using namespace std;
typedef long long ll;
const int N= 2e5 + 5 ;
const int inf= 1e9 + 7 ;
int n, m, p, d[ N] , h[ N] , t[ N] , ans;
int a[ N] , pre[ N] , s[ N] ;
int f[ 2 ] [ N] , cur= 0 , line[ 2 ] [ N] , L[ 2 ] , R[ 2 ] ;
int read ( )
{
int x= 0 , f= 1 ;
char c= getchar ( ) ;
while ( c< '0' || c> '9' ) { if ( c== '-' ) f= - 1 ; c= getchar ( ) ; }
while ( c>= '0' && c<= '9' ) { x= ( x<< 1 ) + ( x<< 3 ) + c- '0' ; c= getchar ( ) ; }
return f* x;
}
void init ( )
{
FOR ( i, 2 , n) s[ i] = s[ i- 1 ] + d[ i] ;
FOR ( i, 1 , m) a[ i] = t[ i] - s[ h[ i] ] ;
sort ( a+ 1 , a+ m+ 1 ) ;
FOR ( i, 1 , m) pre[ i] = pre[ i- 1 ] + a[ i] ;
return ;
}
double slope ( int i, int j, int tag)
{
double ret= 1.0 * ( f[ tag] [ j] - f[ tag] [ i] ) / ( 1.0 * ( j- i) ) ;
return ret;
}
void DP ( )
{
line[ cur^ 1 ] [ L[ cur^ 1 ] = R[ cur^ 1 ] = 1 ] = 0 ;
FOR ( round, 1 , p)
{
cur^ = 1 ;
line[ cur^ 1 ] [ L[ cur^ 1 ] = R[ cur^ 1 ] = 1 ] = 0 ;
FOR ( i, 1 , m)
{
while ( L[ cur] < R[ cur] && line[ cur] [ L[ cur] + 1 ] < i&& slope ( line[ cur] [ L[ cur] ] , line[ cur] [ L[ cur] + 1 ] , cur^ 1 ) < a[ i] ) L[ cur] ++ ;
f[ cur] [ i] = f[ cur^ 1 ] [ line[ cur] [ L[ cur] ] ] - line[ cur] [ L[ cur] ] * a[ i] + i* a[ i] ;
while ( L[ cur^ 1 ] < R[ cur^ 1 ] && slope ( line[ cur^ 1 ] [ R[ cur^ 1 ] - 1 ] , line[ cur^ 1 ] [ R[ cur^ 1 ] ] , cur) > slope ( line[ cur^ 1 ] [ R[ cur^ 1 ] ] , i, cur) ) R[ cur^ 1 ] -- ;
line[ cur^ 1 ] [ ++ R[ cur^ 1 ] ] = i;
}
}
ans= f[ cur] [ m] - pre[ m] ;
return ;
}
int main ( )
{
n= read ( ) , m= read ( ) , p= read ( ) ;
FOR ( i, 2 , n) d[ i] = read ( ) ;
FOR ( i, 1 , m) h[ i] = read ( ) , t[ i] = read ( ) ;
init ( ) ;
DP ( ) ;
printf ( "%d\n" , ans) ;
return 0 ;
}
T2赛后代码
#include <bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
const int N= 1010 ;
int n, m, G[ N] [ N] , vis[ N] [ N] , vis1[ N] , vis2[ N] , cntx[ N] , cnty[ N] ;
char A[ N] [ N] , B[ N] [ N] , l= 1 , r= 0 , tag= 0 ;
pii line[ N] ;
int eq ( )
{
FOR ( i, 1 , n) FOR ( j, 1 , m) if ( A[ i] [ j] != B[ i] [ j] ) return 0 ;
return 1 ;
}
int main ( )
{
scanf ( "%d %d" , & n, & m) ;
FOR ( i, 1 , n) scanf ( "%s" , A[ i] + 1 ) ;
FOR ( i, 1 , n) scanf ( "%s" , B[ i] + 1 ) ;
if ( eq ( ) ) { printf ( "1\n" ) ; exit ( 0 ) ; }
FOR ( i, 1 , n) FOR ( j, 1 , m) if ( B[ i] [ j] == 'X' ) cntx[ i] ++ , cnty[ j] ++ , G[ i] [ j] = 1 ;
FOR ( i, 1 , n) FOR ( j, 1 , m) if ( B[ i] [ j] == 'X' && cntx[ i] == 1 && cnty[ j] == 1 ) line[ ++ r] = mp ( i, j) , vis[ i] [ j] = 1 ;
while ( l<= r)
{
pii tmp= line[ l++ ] ;
if ( vis1[ tmp. fi] <= 1 )
{
vis1[ tmp. fi] ++ ;
FOR ( i, 1 , m) if ( G[ tmp. fi] [ i] == 1 ) cntx[ tmp. fi] -- , cnty[ i] -- , G[ tmp. fi] [ i] = 2 ;
FOR ( i, 1 , m) if ( cntx[ tmp. fi] == 0 && cnty[ i] == 0 && ! vis[ tmp. fi] [ i] ) vis[ tmp. fi] [ i] = 1 , line[ ++ r] = mp ( tmp. fi, i) ;
}
if ( vis2[ tmp. se] <= 1 )
{
vis2[ tmp. se] ++ ;
FOR ( i, 1 , n) if ( G[ i] [ tmp. se] == 1 ) cntx[ i] -- , cnty[ tmp. se] -- , G[ i] [ tmp. se] = 2 ;
FOR ( i, 1 , n) if ( cntx[ i] == 0 && cnty[ tmp. se] == 0 && ! vis[ i] [ tmp. se] ) vis[ i] [ tmp. se] = 1 , line[ ++ r] = mp ( i, tmp. se) ;
}
}
FOR ( i, 1 , n) if ( vis1[ i] ) FOR ( j, 1 , m) if ( vis2[ j] ) if ( A[ i] [ j] == 'O' ) tag= 1 ;
if ( ! tag) { printf ( "0\n" ) ; exit ( 0 ) ; }
FOR ( i, 1 , n) if ( ! vis1[ i] ) FOR ( j, 1 , m) if ( ! vis2[ j] ) if ( A[ i] [ j] != B[ i] [ j] ) { printf ( "0\n" ) ; exit ( 0 ) ; }
printf ( "1\n" ) ;
return 0 ;
}