A artwork
离线并查集维护,然后逐步撤销。撤销后若为白点,判断上下左右不同连通块的数目k,ans[op] -= (k-1) 。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll ;
int par[1<<20] ;
int ma[1010][1010] ;
struct node{
int x1 , y1 , x2 , y2 ;
}operation[100020];
int ans[100020] ;
int find1(int x){
if(x == par[x]) return x ;
return par[x] = find1(par[x]) ;
}
int unite(int x , int y){
int a = find1(x) ; int b = find1(y) ;
if(a == b) return 0 ;
if(a > b) swap(a , b) ;
par[b] = a ;
return 1 ;
}
int n , m , op ;
int dx[4] = {-1 , 0 , 1 , 0} ;
int dy[4] = {0 , -1 , 0 , 1} ;
int work(int x , int y , int value){
if(ma[x][y] != value) return 0 ;
ma[x][y] = 0 ;
int ans = 1 ;
for(int i = 0 ; i <= 3 ; i ++ ){
int xn = x + dx[i] , yn = y + dy[i] ;
if(xn <= 0 || xn > m || yn <= 0 || yn > n || ma[xn][yn] ) continue ;
ans -= unite(x<<10|y , xn<<10|yn) ;
}
return ans ;
}
int init(){
int ans = 0 ;
for(int i = 1 ; i <= m ; i ++ ){
for(int j = 1 ; j <= n ; j ++ ){
ans += work(i , j , 0) ;
}
}
return ans ;
}
int main(){
int a , b , c , d;
while( ~ scanf("%d %d %d" , &n , &m , &op)){
memset(ma , 0 , sizeof(ma)) ;
for(int i = 1 ; i <= op ; i ++ ){
node & te = operation[i] ;
scanf("%d %d %d %d" , &te.y1 , &te.x1 , &te.y2 , &te.x2) ;
if(te.y1 > te.y2) swap(te.y1 , te.y2) ;
if(te.x1 > te.x2) swap(te.x1 , te.x2) ;
}
for(int i = 0 ; i < 1<<20 ; i ++ ) par[i] = i ;
for(int i = op ; i >= 1 ; i -- ){
node & te = operation[i] ;
if(te.x1 == te.x2) for(int j = te.y1 ; j <= te.y2 ; j ++ ){ ma[te.x1][j] = i ; }
else for(int j = te.x1 ; j <= te.x2 ; j ++ ) {ma[j][te.y1] = i ;}
}
/*for(int i = 1 ; i <= m ; i ++ ){
for(int j = 1 ; j <= n ; j ++ )
cout << ma[i][j] << " " ;
cout << endl ;
}*/
ans[op + 1] = init() ;
for(int i = op ; i >= 2 ; i -- ){
node & te = operation[i] ;
ans[i] = ans[i + 1] ;
if(te.x1 == te.x2){
for(int j = te.y1 ; j <= te.y2 ; j ++ )
ans[i] += work(te.x1 , j , i) ;
}else{
for(int j = te.x1 ; j <= te.x2 ; j ++ )
ans[i] += work(j , te.y1 , i) ;
}
}
for(int i = 2 ; i <= op + 1; i ++ ) printf("%d\n" , ans[i]) ;
}
return 0 ;
}
#include <bits/stdc++.h>
using namespace std;
const int maxn = 310;
const int inf = 0x3f3f3f3f;
const int N = 1001 ;
int ma[1505][1505] ;
int par[1505][1505] ;
struct point { int x , y ;};
struct node{
int x1 , y1 , x2 , y2 ;
node(){}
node(int a , int b , int c , int d) : x1(a) , y1(b) , x2(c) , y2(d){}
}operation[10050];
int n , m , q ;
int ans[10050] ;
int find1(int i , int j ){
if(par[i][j] == ( i - 1 ) * m + j ) return par[i][j] ;
return par[i][j] = find1( par[i][j] / m + 1 , par[i][j] % m ) ;
}
int dx[4] = {0 , -1 , 0 , 1} ;
int dy[4] = {-1 , 0 , 1 , 0} ;
int init(){
set<int> ppp ; ppp.clear() ;
memset(par, 0 , sizeof(par)) ;
for(int i = 1 ; i <= n ; i ++ ){
for(int j = 1 ; j <= m ; j ++ ){
if(ma[i][j]) continue ;
for(int k = 0 ; k <= 3 ; k ++){
if(par[ i + dx[k] ][ j + dy[k] ]){ par[i][j] = par[ i + dx[k] ][ j + dy[k] ] ; break ; }
}
if( ! par[i][j] ) par[i][j] = (i - 1) * m + j ;
ppp.insert(par[i][j]) ;
}
}
return ppp.size() ;
}
void unite(int x1 , int y1 , int x2 , int y2){
int a = find1(x1 , y1) , b = find1(x2 , y2) ;
if(a == b) return ;
if(a!= 0 && b!=0){
a = min(a , b) ;
}
else{
a = max(a , b) ;
}
par[x1][y1] = a ;
par[x2][y2] = a ;
}
/*
4 4 4
2 1 2 4
1 2 4 2
3 4 3 4
4 3 4 3
*/
int main()
{
while( ~ scanf("%d %d %d" , &n , &m , &q)){
memset(ma , 0 , sizeof(ma)) ;
memset(ans , 0 , sizeof( ans )) ;
int pos = 0 ;
int a , b , c , d ;
for(int i = 0 ; i < q ; i ++ ){
scanf("%d %d %d %d" , &a , &b , &c , &d) ;
if(a == c){
int e = min(b , d) ; int f = max(b , d) ;
operation[i] = node( a , e , a , f ) ;
for(int j = e ; j <= f ; j ++) {
ma[a][j] ++ ;
}
}else if(b == d){
int e = min(a , c) ; int f = max(a , c ) ;
operation[i] = node( e , b , f , b ) ;
for(int j = e ; j <= f ; j ++ ){
ma[j][b] ++ ;
}
}
}
ans[q] = init() ;
node temp ;
set<int> pq ;
for(int op = q - 1 ; op >= 0 ; op -- ){
temp = operation[op] ;
ans[op] = ans[op + 1] ;
a = temp.x1 , b = temp.y1 , c = temp.x2 , d = temp.y2 ;
if( a == c ){
for(int i = b ; i <= d ; i ++ ){
ma[a][i] -- ;
if(! ma[a][i]){
pq.clear() ;
for(int k = 0 ; k <= 3 ; k ++ ){
if( a + dx[k] > n || a + dx[k] <= 0 || i + dy[k] > m || i + dy[k] <= 0 ) continue ;
if(! par[ a + dx[k] ][ i + dy[k] ] ) continue ;
pq.insert( find1( a + dx[k] , i + dy[k] ) ) ;
}
ans[op] = ans[op] - pq.size() + 1 ;
for(int k = 0 ; k <= 3 ; k ++ ){
if( a + dx[k] > n || a + dx[k] <= 0 || i + dy[k] > m || i + dy[k] <= 0 || !par[ a + dx[k] ][ i + dy[k] ] ) continue ;
unite( a , i , a + dx[k] , i + dy[k] ) ;
/*if( op == 3 ){ cout << ans[op] << " " << pq.size() << " >>>>" << endl ; cout << par[4][4] << " ??" << endl ;
for(int i = 1 ; i <= n ; i ++ ){
for(int j = 1 ; j <= m ; j ++ )
cout << par[i][j] << " " ;
cout << endl ;
}
}*/
}
if(par[a][i] == 0) par[a][i] = (a - 1 )* m + i ;
}
}
}else if( b == d ){
for(int i = a ; i <= c ; i ++ ){
ma[i][b] -- ;
if( ! ma[i][b] ){
pq.clear() ;
for(int k = 0 ; k <= 3 ; k ++ ){
if( i + dx[k] > n || i + dx[k] <= 0 || b + dy[k] > m || b + dy[k] <= 0 ) continue ;
if(! par[ i + dx[k] ][ b + dy[k] ] ) continue ;
pq.insert( find1( i + dx[k] , b + dy[k] ) ) ;
}
ans[op] = ans[op] - pq.size() + 1 ;
for(int k = 0 ; k <= 3 ; k ++ ){
if( i + dx[k] > n || i + dx[k] <= 0 || b + dy[k] > m || b + dy[k] <= 0 || !par[ i + dx[k] ][ b + dy[k] ]) continue ;
unite( i , b , i + dx[k] , b + dy[k] ) ;
}
if(par[i][b] == 0) par[i][b] = ( i - 1 )* m + b ;
}
}
}
}
for(int i = 1 ; i <= q ; i ++ )
printf("%d\n" , ans[i]) ;
}
return 0;
}
B. Bless You Autocorrect!
unsolved
C. Card Hand Sorting
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
template <class It> int lisLength(It begin, It end) {
typedef typename iterator_traits<It>::value_type T;
T inf = 1<<30;
vector<T> best(end-begin,inf);
for (It i = begin; i != end; ++i)
*lower_bound(best.begin(),best.end(),*i) = *i;
return lower_bound(best.begin(),best.end(),inf)-best.begin();
}
int main() {
int n;
cin >> n;
vector< pair<int, int> > hand(n, pair<int, int>(0,0) );
map<char, int> rank;
rank['T'] = 10;
rank['J'] = 11;
rank['Q'] = 12;
rank['K'] = 13;
rank['A'] = 14;
map<char, int> suit;
suit['s'] = 0;
suit['h'] = 1;
suit['d'] = 2;
suit['c'] = 3;
char s[3];
for (int i = 0; i < n; ++i) {
cin >> s;
if (rank.count(s[0]))
hand[i].first = rank[s[0]];
else
hand[i].first = s[0]-'0';
hand[i].second = suit[s[1]];
}
int suit_order[] = {0, 1, 2, 3};
int res = 0;
for (int order = 0; order < 4*3*2; ++order) {
for (int direction = 0; direction < 16; ++direction) {
vector<int> value(n, 0);
for (int i = 0; i < n; ++i) {
value[i] = suit_order[hand[i].second]*100 +
hand[i].first * (1 - 2*!!(direction&(1<<hand[i].second)));
//cout << value[i] << " ";
}
//cout << endl;
/*if (lisLength(value.begin(), value.end()) > res) {
for (int i = 0; i < n; ++i) {
cout << value[i] << " ";
}
cout << endl;
}*/
res = max(res, lisLength(value.begin(), value.end()));
}
next_permutation(suit_order, suit_order+4);
}
cout << n-res << endl;
}
D. Daydreaming Stockbroker
简单链表模拟
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 1000
typedef long long ll ;
ll sa[500] ;
ll check(ll total , ll a){
ll ans ;
ans = total / a ;
if(ans >= 100000) return 100000 ;
return ans ;
}
int main() {
int n ;
while( ~ scanf("%d" , &n)){
for(int i = 0 ; i < n ; i ++ ){
scanf("%lld" , &sa[i]) ;
}
bool flag= 0 ;
ll total = 100 ;
ll pre = 0 ;
ll gu = 0 ;
for(int i = 1 ; i < n ; i ++ ){
if( !flag ){
if(sa[i] >= sa[i-1]) {flag = 1 ; gu = check(total , sa[i-1]) ; total -= sa[i-1] * gu ; }
else{
}
}else if(flag){
if(sa[i] >= sa[i-1]){
}
else{
total += gu * sa[i-1] ;
flag = 0 ;
}
}
}
if(flag){
total += gu * sa[n - 1] ;
}
printf("%lld\n" , total) ;
}
return 0;
}
E. Exponial
欧拉递推
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
ll n,m,ans;
ll euler(ll n){
ll res=n,a=n;
for(ll i=2;i*i<=a;i++){
if(a%i==0){
res=res/i*(i-1);
while(a%i==0) a/=i;
}
}
if(a>1) res=res/a*(a-1);
return res;
}
ll fast_mod(ll x,ll n,ll Max)
{
ll res=1;
while(n>0)
{
if(n & 1)
res=(res*x)%Max;
x=(x*x)%Max;
n >>= 1;
}
return res;
}
ll func(ll n,ll m){
if(m==1) return 0;
if(n<=5){
ll ans=1;
for(int i=1;i<=n;i++){
ans=fast_mod(i,ans,m);
}
return ans;
}else{
ll phi=euler(m);
ll z=func(n-1,phi);
ans=fast_mod(n,phi+z,m);
}
return ans;
}
int main(){
while( ~ scanf("%lld %lld" , &n , &m))
printf("%lld\n" , func(n , m)) ;
return 0;
}
F. Fleecing the Raffle
概率dp
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
ll n , m ;
double dp[100050] ;
/*double solve(double parameter)
{
double k = 1 ;
for(ll i = n - m + 2 ; i <= n ; i ++ ) k = k * i / (i - 1 + parameter) ;
k = k * parameter * m / (n + parameter) ;
return k ;
}
double trisection_search(double left, double right)
{
double midl, midr;
while (right-left > 1)
{
midl = (left + right) / 2;
midr = (midl + right) / 2;
if(solve(midl) >= solve(midr)) right = midr;
else left = midl;
}
return left;
}*/
int main(){
while( ~ scanf("%lld %lld" , &n , &m))
{
memset(dp , 0 , sizeof(dp)) ;
dp[1] = 1 ;
for(ll i = n - m + 2 ; i <= n ; i ++ ) dp[1] = dp[1] * i / ( i - 1 + 1) ;
dp[1] = dp[1] * m / (n + 1) ;
double ans = dp[1] ;
for(ll i = 2 ; i <= n ; i ++ ){
dp[i] = dp[i-1] * i / ( i - 1 ) * ( n + i - m ) / (n + i) ;
ans = max(ans , dp[i]) ;
if(dp[i] <= dp[i-1]) break ;
}
printf("%.8f\n" , ans ) ;
}
return 0;
}
G. Game Rank
炉石
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
char a[10005];
int prank(int a){
if(a<=25&&a>=21)
return 2;
if(a<=20&&a>=16)
return 3;
if(a<=15&&a>=11)
return 4;
if(a<=10&&a>=1)
return 5;
if(a<=0)
return 1;
}
int main()
{
while(~scanf("%s",a)){
int ranka=25;
int p=0;
int star=0;
for(int i=0;a[i]!='\0';i++){
if(a[i]=='L'){
p=0;
if(ranka<=25&&ranka>=21)
continue;
if((ranka==25||ranka==20||ranka<=0)&&!star){continue;}
else{
if(star)
star--;
else{
ranka++;
if(prank(ranka) == 1)
star = 0 ;
else
star = prank(ranka)-1;
}
}
}
else{
p ++ ;
if(ranka <= 5)
p = 0 ;
if(ranka <= 0)
continue;
else{
if(p >= 3)
star += 2;
else
star += 1;
while(1){
if(star > prank(ranka)){
star -= prank(ranka);
ranka -- ;
}
else
break;
}
}
}
}
if(ranka<=0)
printf("Legend\n");
else
printf("%d\n",ranka);
memset(a,'\0',sizeof(a));
}
return 0;
}
J. Jumbled Compass
水题
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std ;
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
int main(){
int m , n ;
int ans ;
while( ~ scanf("%d %d" , &m , &n)){
if(m == n) { printf("%d\n" , 0) ; continue ;}
int a ;
if(n >= m) a = n - m ; else a = n + 360 - m ;
int b ;
if(m < n)b = m + 360 - n ; else b = m - n ;
ans = min(a , b) ;
//if(m + ans == n || (m + ans)% 360 == n ) printf("%d\n" , ans) ;
if(ans == a) printf("%d\n" ,ans) ;
else printf("%d\n" , -ans ) ;
}
return 0 ;
}