ACM ICPC 2017 Warmup Contest 1


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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值