A:1210 Chinese Girls' Amusement
大数。如果n%4==0,输出n/2-1,如果n%2==0&&n%4==1,输出n/2-2,如果n%2==1,输出n/2。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define mid ( ( l + r ) >> 1 )
#define root 1 , 1 , n
const int MAXN = 100006 ;
char s[MAXN] ;
int num[MAXN] ;
void solve () {
int n = strlen ( s ) ;
rep ( i , 0 , n ) num[i] = s[i] - '0' ;
int flag = num[n - 1] & 1 ;
int tmp = 0 ;
rep ( i , 0 , n ) {
num[i] += tmp * 10 ;
tmp = num[i] % 2 ;
num[i] /= 2 ;
}
if ( flag == 1 ) {
if ( num[0] ) printf ( "%d" , num[0] ) ;
rep ( i , 1 , n ) printf ( "%d" , num[i] ) ;
printf ( "\n" ) ;
} else {
int del = 1 ;
rev ( i , n - 1 , 0 ) {
del = num[i] - del ;
num[i] = del ;
del = 0 ;
if ( num[i] < 0 ) {
num[i] += 10 ;
del = 1 ;
}
}
if ( ( num[n - 1] & 1 ) == 0 ) {
int del = 1 ;
rev ( i , n - 1 , 0 ) {
del = num[i] - del ;
num[i] = del ;
del = 0 ;
if ( num[i] < 0 ) {
num[i] += 10 ;
del = 1 ;
}
}
}
if ( num[0] ) printf ( "%d" , num[0] ) ;
rep ( i , 1 , n ) printf ( "%d" , num[i] ) ;
printf ( "\n" ) ;
}
}
int main () {
while ( gets ( s ) ) solve () ;
return 0 ;
}
裸的带下界的可行流。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define mid ( ( l + r ) >> 1 )
#define root 1 , 1 , n
const int MAXN = 205 ;
const int MAXE = 1000000 ;
const int INF = 0x3f3f3f3f ;
struct Edge {
int v , c , n ;
Edge () {}
Edge ( int v , int c , int n ) : v ( v ) , c ( c ) , n ( n ) {}
} E[MAXE] ;
int H[MAXN] , cntE ;
int d[MAXN] , cur[MAXN] , pre[MAXN] , num[MAXN] ;
int Q[MAXN] , head , tail ;
int s , t , nv ;
int flow ;
int n , m ;
int in[MAXN] , ou[MAXN] ;
int low[MAXE] ;
void clear () {
cntE = 0 ;
clr ( H , -1 ) ;
clr ( in , 0 ) ;
clr ( ou , 0 ) ;
}
void addedge ( int u , int v , int c ) {
E[cntE] = Edge ( v , c , H[u] ) ;
H[u] = cntE ++ ;
E[cntE] = Edge ( u , 0 , H[v] ) ;
H[v] = cntE ++ ;
}
void rev_bfs () {
clr ( d , -1 ) ;
clr ( num , 0 ) ;
head = tail = 0 ;
Q[tail ++] = t ;
d[t] = 0 ;
num[0] = 1 ;
while ( head != tail ) {
int u = Q[head ++] ;
for ( int i = H[u] ; ~i ; i = E[i].n ) {
int v = E[i].v ;
if ( ~d[v] ) continue ;
d[v] = d[u] + 1 ;
num[d[v]] ++ ;
Q[tail ++] = v ;
}
}
}
int ISAP () {
rev_bfs () ;
cpy ( cur , H ) ;
flow = 0 ;
int u = pre[s] = s , i , pos , f , minv ;
while ( d[s] < nv ) {
if ( u == t ) {
f = INF ;
for ( i = s ; i != t ; i = E[cur[i]].v ) {
if ( f > E[cur[i]].c ) {
f = E[cur[i]].c ;
pos = i ;
}
}
for ( i = s ; i != t ; i = E[cur[i]].v ) {
E[cur[i]].c -= f ;
E[cur[i] ^ 1].c += f ;
}
flow += f ;
u = pos ;
}
for ( i = cur[u] ; ~i ; i = E[i].n ) {
if ( E[i].c && d[u] == d[E[i].v] + 1 ) break ;
}
if ( ~i ) {
cur[u] = i ;
pre[E[i].v] = u ;
u = E[i].v ;
} else {
if ( 0 == --num[d[u]] ) break ;
for ( minv = nv , i = H[u] ; ~i ; i = E[i].n ) {
if ( E[i].c && minv > d[E[i].v] ) {
minv = d[E[i].v] ;
cur[u] = i ;
}
}
d[u] = minv + 1 ;
num[d[u]] ++ ;
u = pre[u] ;
}
}
return flow ;
}
void solve () {
int u , v , c ;
clear () ;
s = 0 ;
t = n + 1 ;
nv = t + 1 ;
rep ( i , 0 , m ) {
scanf ( "%d%d%d%d" , &u , &v , &low[i] , &c ) ;
in[v] += low[i] ;
ou[u] += low[i] ;
addedge ( u , v , c - low[i] ) ;
}
For ( i , 1 , n ) {
int tmp = in[i] - ou[i] ;
if ( tmp > 0 ) addedge ( s , i , tmp ) ;
if ( tmp < 0 ) addedge ( i , t , -tmp ) ;
}
ISAP () ;
int ok = 1 ;
for ( int i = H[s] ; ~i ; i = E[i].n ) if ( E[i].c ) ok = 0 ;
if ( ok == 0 ) {
printf ( "NO\n" ) ;
} else {
printf ( "YES\n" ) ;
rep ( i , 0 , m ) printf ( "%d\n" , low[i] + E[i << 1 | 1].c ) ;
}
}
int main () {
while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ;
return 0 ;
}
所有边的两个点的度之和即答案。观察找规律可知,两个矩阵相乘时如果对应位置为1则必定是两条线段有公共点。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define mid ( ( l + r ) >> 1 )
#define root 1 , 1 , n
const int MAXN = 10005 ;
const int MAXE = 100005 ;
struct Seg {
int u , v ;
} seg[MAXE] ;
int num[MAXN] ;
int n , m ;
void solve () {
clr ( num , 0 ) ;
rep ( i , 0 , m ) {
scanf ( "%d%d" , &seg[i].u , &seg[i].v ) ;
num[seg[i].u] ++ ;
num[seg[i].v] ++ ;
}
LL ans = 0 ;
rep ( i , 0 , m ) {
ans += num[seg[i].u] ;
ans += num[seg[i].v] ;
}
printf ( "%lld\n" , ans ) ;
}
int main () {
while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ;
return 0 ;
}
E:1214 Nice Patterns Strike Back
因为下一列只与上一列的状态有关,可以暴力判断预处理出转移矩阵。高精度+矩阵快速幂,比赛的时候高精度写错了,蛋疼死。。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define mid ( ( l + r ) >> 1 )
#define root 1 , 1 , cnt
const int M = 50 ;
const int L = 10 ;
int mod ;
struct BigInt {
int digit[1005] ;
int length ;
BigInt () {}
BigInt ( char buf[] ) : length ( 0 ) {
clr ( digit , 0 ) ;
length = strlen ( buf ) ;
rep ( i , 0 , length ) digit[i] = buf[length - i - 1] - '0' ;
}
int operator [] ( const int& index ) const {
return digit[index] ;
}
int& operator [] ( const int& index ) {
return digit[index] ;
}
BigInt fix () {
while ( length && digit[length - 1] == 0 ) -- length ;
return *this ;
}
BigInt operator / ( const int& b ) {
BigInt c ;
c.length = length ;
int tmp = 0 ;
rev ( i , length - 1 , 0 ) {
c[i] = digit[i] + tmp * 10 ;
tmp = c[i] % b ;
c[i] /= b ;
}
return c.fix () ;
}
BigInt operator - ( const int& b ) {
BigInt c ;
c.length = length ;
int tmp = b ;
rep ( i , 0 , length ) {
tmp = digit[i] - tmp ;
c[i] = tmp ;
tmp = 0 ;
if ( c[i] < 0 ) {
c[i] += 10 ;
tmp = 1 ;
}
}
return c.fix () ;
}
void show () {
if ( length == 0 ) {
printf ( "0\n" ) ;
return ;
}
printf ( "%d" , digit[length - 1] ) ;
rev ( i , length - 2 , 0 ) printf ( "%d" , digit[i] ) ;
printf ( "\n" ) ;
}
} ;
struct Matrix {
int mat[M][M] ;
int n ;
Matrix () {
clr ( mat , 0 ) ;
}
Matrix ( int n ) : n ( n ) {
clr ( mat , 0 ) ;
}
void eyes () {
clr ( mat , 0 ) ;
rep ( i , 0 , n ) mat[i][i] = 1 ;
}
void empty () {
clr ( mat , 0 ) ;
}
Matrix operator * ( const Matrix& a ) const {
Matrix c ( n ) ;
rep ( i , 0 , n ) rep ( j , 0 , n ) rep ( k , 0 , n ) {
c.mat[i][j] = ( c.mat[i][j] + mat[i][k] * a.mat[k][j] ) % mod ;
}
return c ;
}
void show () {
rep ( i , 0 , n ) {
rep ( j , 0 , n ) printf ( "%d " , mat[i][j] ) ;
printf ( "\n" ) ;
}
}
} ;
Matrix A[6] ;
char buf[500] ;
int m ;
int check ( int a , int b , int n ) {
int cnt1 = 0 ;
int cnt2 = 0 ;
rep ( i , 0 , n ) {
if ( a % 2 == 0 && b % 2 == 0 ) {
cnt1 ++ ;
cnt2 = 0 ;
if ( cnt1 == 2 ) return 0 ;
} else if ( a % 2 == 1 && b % 2 == 1 ) {
cnt2 ++ ;
cnt1 = 0 ;
if ( cnt2 == 2 ) return 0 ;
} else cnt1 = cnt2 = 0 ;
a >>= 1 ;
b >>= 1 ;
}
return 1 ;
}
void fun () {
For ( i , 1 , 5 ) {
int S = 1 << i ;
A[i].n = S ;
A[i].empty () ;
rep ( j , 0 , S ) {
rep ( k , 0 , S ) {
if ( check ( j , k , i ) ) A[i].mat[j][k] = 1 ;
}
}
}
}
Matrix pow ( Matrix& a , BigInt& b ) {
Matrix res ( a.n ) ;
Matrix tmp = a ;
res.eyes () ;
while ( b.length ) {
if ( b[0] & 1 ) res = res * tmp ;
tmp = tmp * tmp ;
b = b / 2 ;
}
return res ;
}
void solve () {
BigInt c ( buf ) ;
c = c - 1 ;
Matrix res = pow ( A[m] , c ) ;
int S = 1 << m ;
int ans = 0 ;
rep ( i , 0 , S ) rep ( j , 0 , S ) ans = ( ans + res.mat[i][j] ) % mod ;
printf ( "%d\n" , ans ) ;
}
int main () {
fun () ;
while ( ~scanf ( "%s%d%d" , buf , &m ,&mod ) ) solve () ;
return 0 ;
}
线段树优化DP。
先将所有点按照第一个关键字排序,将第二个关键字离散化。然后按第一关键字从小到大扫所有的人,一段一段的更新第一关键字相同的。每一段相同关键字的人用query求出他的最优值,以及最优值对应的id,然后更新前驱,接下来用栈保存他的信息,直到所有第一关键字相同的人都查询完后,再将栈中保存的信息用以更新线段树,线段树中以b作为下标,每个区间保存这个区间的最大单调子序列的长度以及结尾元素的id。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std ;
typedef long long LL ;
#define rep( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define For( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define rev( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define clr( a , x ) memset ( a , x , sizeof a )
#define cpy( a , x ) memcpy ( a , x , sizeof a )
#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define mid ( ( l + r ) >> 1 )
#define root 1 , 1 , cnt
const int MAXN = 300005 ;
struct Node {
int a , b , idx ;
bool operator < ( const Node& t ) const {
return a < t.a ;
}
} node[MAXN] ;
struct Stack {
int pos , max , idx ;
Stack () {}
Stack ( int pos , int max , int idx ) : pos ( pos ) , max ( max ) , idx ( idx ) {}
} S[MAXN] ;
int top ;
int pre[MAXN] ;
int maxv[MAXN << 2] ;
int idx[MAXN << 2] ;
int a[MAXN] , cnt ;
int n ;
int unique ( int n ) {
int cnt = 1 ;
sort ( a + 1 , a + n + 1 ) ;
For ( i , 2 , n ) if ( a[i] != a[cnt] ) a[++ cnt] = a[i] ;
return cnt ;
}
int hash ( int x ) {
int l = 1 , r = cnt ;
while ( l < r ) {
int m = ( l + r ) >> 1 ;
if ( a[m] >= x ) r = m ;
else l = m + 1 ;
}
return l ;
}
void update ( int x , int _max , int _idx , int o , int l , int r ) {
while ( l < r ) {
int m = ( l + r ) >> 1 ;
if ( x <= m ) {
o = o << 1 ;
r = m ;
} else {
o = o << 1 | 1 ;
l = m + 1 ;
}
}
maxv[o] = _max ;
idx[o] = _idx ;
while ( o > 1 ) {
o >>= 1 ;
if ( maxv[ls] > maxv[rs] ) {
maxv[o] = maxv[ls] ;
idx[o] = idx[ls] ;
} else {
maxv[o] = maxv[rs] ;
idx[o] = idx[rs] ;
}
}
}
int query_idx , query_max ;
int stack[MAXN] ;
void query ( int L , int R , int o , int l , int r ) {
if ( L > R ) return ;
if ( L <= l && r <= R ) {
if ( query_max < maxv[o] ) {
query_max = maxv[o] ;
query_idx = idx[o] ;
}
return ;
}
int m = mid ;
if ( L <= m ) query ( L , R , lson ) ;
if ( m < R ) query ( L , R , rson ) ;
}
void solve () {
cnt = 0 ;
clr ( pre , 0 ) ;
clr ( maxv , 0 ) ;
clr ( idx , 0 ) ;
For ( i , 1 , n ) {
scanf ( "%d%d" , &node[i].a , &node[i].b ) ;
node[i].idx = i ;
a[++ cnt] = node[i].b ;
}
cnt = unique ( cnt ) ;
sort ( node + 1 , node + n + 1 ) ;
For ( i , 1 , n ) {
int j = i ;
top = 0 ;
while ( j <= n && node[i].a == node[j].a ) {
query_idx = 0 ;
query_max = 0 ;
int R = hash ( node[j].b ) ;
query ( 1 , R - 1 , root ) ;
pre[node[j].idx] = query_idx ;
S[top ++] = Stack ( R , query_max + 1 , node[j].idx ) ;
//printf ( "%d %d %d\n" , R , query_max + 1 , j ) ;
++ j ;
}
rep ( k , 0 , top ) update ( S[k].pos , S[k].max , S[k].idx , root ) ;
i = j - 1 ;
}
printf ( "%d\n" , maxv[1] ) ;
top = 0 ;
for ( int i = idx[1] ; i ; i = pre[i] ) {
stack[top ++] = i ;
}
sort ( stack , stack + top ) ;
rep ( i , 0 , top ) printf ( "%d%c" , stack[i] , i < top - 1 ? ' ' : '\n' ) ;
}
int main () {
scanf ( "%d" , &n ) ;
solve () ;
return 0 ;
}