题解:
T1:收益如果一个人同时支持两个议题,那么它一定会入选。接下来按01和10两两配对接着取,配完之后剩下的都和00无异,从大往小选即可。
O(N log N)

# include <bits/stdc++.h>
using namespace std;
namespace Base{
    # define mr make_pair
    typedef long long ll;
    typedef double db;
    const int inf = 0x3f3f3f3f, INF = 0x7fffffff;
    const ll  infll = 0x3f3f3f3f3f3f3f3fll, INFll = 0x7fffffffffffffffll;
    template<typename T> void read(T &x){
        x = 0; int fh = 1; double num = 1.0; char ch = getchar();
        while (!isdigit(ch)){ if (ch == '-') fh = -1; ch = getchar(); }
        while (isdigit(ch)){ x = x * 10 + ch - '0'; ch = getchar(); }
        if (ch == '.'){
            ch = getchar();
            while (isdigit(ch)){num /= 10; x = x + num * (ch - '0'); ch = getchar();}
        }
        x = x * fh;
    }
    template<typename T> void chmax(T &x, T y){x = x < y ? y : x;}
    template<typename T> void chmin(T &x, T y){x = x > y ? y : x;}
}
using namespace Base;

const int N = 1000010;
int n, val[4][N], num[4], ans;
bool cmp(int x, int y){
    return x > y;
}
int main(){
    freopen("debate.in", "r", stdin);
    freopen("debate.out", "w", stdout);
    read(n);
    for (int i = 1; i <= n; i++){
        int x, v, c;
        read(x); read(v);
        if (x == 11) c = 0;
        if (x == 10) c = 1;
        if (x == 01) c = 2;
        if (x == 00) c = 3;
        val[c][++num[c]] = v;
    }
    sort(val[1] + 1, val[1] + num[1] + 1, cmp);
    sort(val[2] + 1, val[2] + num[2] + 1, cmp);
    int mn = min(num[1], num[2]);
    for (int i = 1; i <= mn; i++)
        ans = ans + val[1][i] + val[2][i];
    for (int i = mn + 1; i <= num[1]; i++) val[3][++num[3]] = val[1][i];
    for (int i = mn + 1; i <= num[2]; i++) val[3][++num[3]] = val[2][i];
    sort(val[3] + 1, val[3] + num[3] + 1, cmp);
    for (int i = 1; i <= num[0]; i++) 
        ans = ans + val[0][i] + val[3][i];
    printf("%d\n", ans);
    return 0;
}


T2:不难发现当K=8时可行的合法解就超过100000,所以解是非常多的,直接爆搜即可。
O(能过)

#include <cstdio>

#define filein "hexodoku"

void prepare( )
{
    freopen( filein ".in", "r", stdin );
    freopen( filein ".out", "w", stdout );
}

#include <cmath>
#include <cassert>
#include <memory.h>
#include <vector>
#include <string>
#include <ctime>
#include <algorithm>
#include <functional>

using namespace std;

#define fo(a,b,c) for(a=(b);a<(c);++a)
#define fr(a,b) fo(a,0,(b))
#define fi(a) fr(i,(a))
#define fj(a) fr(j,(a))
#define fk(a) fr(k,(a))
#define _(a,b) memset((a),(b),sizeof(a))
#define __(a) _((a),0)

const int dx[] = { 1, 0, -1, -1, 0, 1, 0 };
const int dy[] = { 0, 1, 1, 0, -1, -1, 0 };

const int MAXN = 7;
const int MAXF = 32;

char f[MAXN][MAXN + 1];
char m[MAXF];
char ansm[MAXF];
int ans;
vector<pair< int, int> > v[MAXN][MAXN];
vector<pair< int, int> > coord;
int p[MAXF][MAXF];
int pn[MAXF];
int need;
int MAXID;
int K, N;

bool test( )
{
    if ( ++ ans < N )
        return false;
    memcpy( ansm, m, sizeof( m ) );
    return true;
}

int makemask( const int &id )
{
    int i;
    int res = 0;
    int *pp = p[id];    
    int ppn = pn[id];
    fi( ppn )
    {
        int cv = m[pp[i]];
        if ( cv >= 0 )
            res |= 1 << cv;
    }
    return res;
}

bool brute( int id )
{
    if ( id == MAXID )
        return test( );
    if ( m[id] >= 0 )
        return brute( id + 1 );
    int mask = makemask( id );
    int i;
    fi( K )
    {
        if ( mask & ( 1 << i ) )
            continue;
        m[id] = i;
        if ( brute( id + 1 ) )
            return true;
        m[id] = -1;
    }
    return false;
}

void buildgraph( )
{
    _( f, -1 );
//    fprintf( stderr, "Build started\n" );
    int i, j, k;    
    fi( 7 ) if ( i <= 7 )
    {
        int y = 3;
        int x = 3;
        if ( i < 6 )
        {
            y += dy[i] * 2 + dy[( i + 4 ) % 6];
            x += dx[i] * 2 + dx[( i + 4 ) % 6];
        }
        fj( 7 )
        {
            int cx = x + dx[j];
            int cy = y + dy[j];
            f[cy][cx] = 0;
            fk( 7 ) if ( k != j )
            {
                v[cy][cx].push_back( make_pair( y + dy[k], x + dx[k] ) );                
            }
        }
    }
    int d;

    fi( MAXN ) fj( MAXN ) if ( !f[i][j] ) fr( d, 6 ) fo( k, 1, MAXN )
    {
        int cy = i + dy[d] * k;
        int cx = j + dx[d] * k;
        if ( cx < 0 || cy < 0 || cx >= MAXN || cy >= MAXN || f[cy][cx] )
            break;
        v[i][j].push_back( make_pair( cy, cx ) );
    }
    MAXID = 0;
    fi( MAXN ) fj( MAXN )
    {
        if ( f[i][j] == 0 )
        {
            coord.push_back( make_pair( i, j ) );
            f[i][j] = MAXID++;
        }
    }
    fi( MAXID )
    {
        vector<pair<int, int> > &tw = v[coord[i].first][coord[i].second];
        sort( tw.begin( ), tw.end( ) );
        tw.resize( unique( tw.begin( ), tw.end( ) ) - tw.begin( ) );
        fj( (int)tw.size( ) )
        {
            p[i][pn[i]++] = f[tw[j].first][tw[j].second];
        }
    }
//    fprintf( stderr, "Build finished\n" );
}

void readfield( )
{
//    fprintf( stderr, "Read started\n" );
    scanf( "%d %d", &K, &N );
    _( m, -1 );
    int i, j;
    fi( MAXID )
    {
        int temp;
        scanf( "%d", &temp );
        if ( temp == 0 )
            m[i] = -1;
        else
            m[i] = temp - 1;
    }
//    fprintf( stderr, "Read finished\n" );
}

void solve( )
{
    clock_t st = clock( );
//    fprintf( stderr, "Solve started\n" );
    if ( brute( 0 ) )
    { 
        printf( "Found\n" );
        memcpy( m, ansm, sizeof( m ) );
        bool first = true;
        int i, j;
        fi( MAXID )
        {
            if ( first ) first = false;
            else printf( " " );
            printf( "%d", m[i] + 1 );
        }
        printf( "\n" );
/*
        fi( MAXN )
        {
            fj( i ) fprintf( stderr, " " );
            fj( MAXN )
            {
                if ( f[i][j] >= 0 )
                {
                    fprintf( stderr, "%2d", m[f[i][j]] );
                }
                else
                    fprintf( stderr, " -" );
            }
            fprintf( stderr, "\n" );
        }
*/    }
    else
    {
        printf( "No way\n" );
    }
    st = clock( ) - st;
}        

int main( )
{
    prepare( );
    int i, j, k;
    buildgraph( );    
    readfield( );
    solve( );

    return 0;

}

T3:50分:我们可以用logN的时间判断出相邻两个点是否同色,宽搜即可。宽搜后可以发现10000以内最大的连通块的面积只有2*10^7级别。
O(答案)
100分:考虑把点分类:
只和下方连通的-1,和右方连通的-1(这两类等价)
同时和下方和右方连通的-1
只和下方连通的1,和右方连通的1(这两类等价)
同时和下方和右方连通的1
对于其余的点,完全在内部的不用讨论,最左和最上的都是1,且它们为infinity,也不要讨论。
在扩展时同时维护这些点的数量,和要求的点所在的位置,具体时间见代码。
O(logN)

#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#define TASKNAME "area"
#define INT64 "%lld"
typedef long long int64;

enum STATE {P0, P1, P2D, P2R, M1, M2D, M2R, STATE_NUM};
const int DX = STATE_NUM, DY = STATE_NUM * 2;

int main (void)
{
 int i, x, y, st;
 int64 area, p0, p1, p2, m1, m2, p0n, p1n, p2n, m1n, m2n;
 freopen (TASKNAME ".in", "rt", stdin);
 freopen (TASKNAME ".out", "wt", stdout);
 while (scanf (" %d %d", &x, &y) != EOF)
 {
  area = p0 = 1; p1 = p2 = m1 = m2 = 0;
  st = P0;
  for (i = 0; i < 31; i++)
  {
   p0n = p0 * 3 + p1 + p2 * 2;
   p1n = m1;
   p2n = p1 + p2 + m2;
   m1n = p0 + p1 + m1 * 2 + m2 * 2;
   m2n = p2 + m2;
   switch (st + DX * ((x >> i) & 1) + DY * ((y >> i) & 1))
   {
    case P0:
    case P1:
    case P2D:
    case P2R:
    case P0 + DX:
    case P0 + DY:
     area = p0n;
     st = P0;
     break;
    case M1 + DX + DY:
     st = P1;
     break;
    case P1 + DY:
    case P2D + DY:
    case M2D + DX + DY:
     st = P2D;
     break;
    case P1 + DX:
    case P2R + DX:
    case M2R + DX + DY:
     st = P2R;
     break;
    case M1 + DX:
    case M2D + DX:
    case M1 + DY:
    case M2R + DY:
    case P0 + DX + DY:
     area = m1n - p1;
     // fallthrough
    case P1 + DX + DY:
     st = M1;
     break;
    case M2D + DY:
    case P2D + DX + DY:
     st = M2D;
     break;
    case M2R + DX:
    case P2R + DX + DY:
     st = M2R;
     break;
    default:
     st = STATE_NUM; // isolated component
     break;
   }
   p0 = p0n;
   p1 = p1n;
   p2 = p2n;
   m1 = m1n;
   m2 = m2n;
   if (st == STATE_NUM) break;
  }
  if (st == P0) printf ("infinity\n");
  else printf (INT64 "\n", area);
 }
 return 0;
}