【ACdream】Andrew Stankevich Contest (1)

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 ;
}



B:1211 Reactor Cooling

裸的带下界的可行流。


#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 ;
}



D:1213 Matrix Multiplication

所有边的两个点的度之和即答案。观察找规律可知,两个矩阵相乘时如果对应位置为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 ;
}



G:1216 Beautiful People

线段树优化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 ;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值