October 20 race simulation solution to a problem

October 20 race simulation solution to a problem

A card

Description

There on the desktop \ (n \) playing cards, each card pros and cons of each written an integer, face up initially. You now requires minimal flip cards, so that the digital up at least half of the numbers are the same, or no solution is determined.

Limitations

\ (. 1 \ n-Leq \ Leq. 3 \ ^. 5 Times 10 \) , all the input data is not greater than \ (10 ^ 9 \) non-negative integer.

Solution

Attendance problem, because the notice requires at least half of the same figure, and a total of only \ (2n \) numbers, so the final numbers may be the same as the number does not exceed \ (4 \) months. With map/hashjust about maintenance occurrences, then more than half of the enumeration figures, violence can be judged.

Code

#include <cstdio>
#include <map>
#include <vector>

const int maxn = 300005;

int n, ans = maxn, dn;
int a[maxn], b[maxn];
std::map<int, int> oc;
std::vector<int> ansv;

int main() {
  freopen("card.in", "r", stdin);
  freopen("card.out", "w", stdout);
  qr(n); dn = (n >> 1) + (n & 1);
  for (int i = 1; i <= n; ++i) {
    qr(a[i]); qr(b[i]);
    if (a[i] != b[i]) {
      if (++oc[a[i]] == dn) {
        ansv.push_back(a[i]);
      }
      if (++oc[b[i]] == dn) {
        ansv.push_back(b[i]);
      }
    } else {
      if (++oc[a[i]] == dn) {
        ansv.push_back(a[i]);
      }
    }
  }
  if (ansv.size() == 0) {
    puts("Impossible");
    return 0;
  }
  for (auto v : ansv) {
    int cnt = 0;
    for (int i = 1; i <= n; ++i) {
      cnt += a[i] == v;
    }
    ans = std::min(ans, dn - cnt);
  }
  printf("%d\n", std::max(0, ans));
}

Group B suffix tree

Description

Given a length \ (n-\) string for each position \ (I \) , and it takes it back \ ((m - 1) \ ) characters were \ (m \) character as the first \ (I \) substrings. (If reaches the end, the length of the substring \ (n--. 1 I + \) ). Now these \ (n \) substring arranged in accordance with the position where the first character in a row, to them in accordance with the lexicographical ordering, you can only swap adjacent strings, find the minimum number of exchanges.

Limitations

For all the data, \ (. 1 \ Leq m \ n-Leq \ Leq 50000 \) , the string contains only lowercase

For the first \ (60 \% \) data, \ (. 1 \ n-Leq \ Leq 5000 \) .

Another \ (10 \% \) data, \ (. 1 \ Leq m \ Leq. 5 \)

Another \ (10 \% \) data, a randomly generated string.

Solution

The first conclusion is that, according to a sequence in descending order and not only to swap adjacent items, the optimal number of exchanges is to reverse the sequence number. The proof can be considered the largest element first to move to the end of the sequence, the number of moving what is needed is the largest element contributed to reverse the number, and then remove the last element sequence, the remaining sequence continues sorted in order to do mathematical induction It can be.

So just know that each sub-string lexicographically rankings, we can \ (O (n \ log n ) \) is calculated answer.

Before considering \ (60 \% \) data may be \ (O (nm) \) to identify each sub-string, then sort by bubbling to \ (O (n ^ 2) \) was determined on reverse number. But probably only zxythis sbwould take bubble to seek to reverse the (

For \ (m \ leq 5 \) data sorted using BITor mergesortseeking just fine.

For random data string, we note that in comparison lexicographic order, when the first character the same probability to enter a comparison is \ (\ FRAC. 1 {{25} \} Times 26 is \) , then a the probability of bit comparison of the probability of the square above. Similarly, we found that every time expect relatively very small number, no more than \ (5 \) , so the sort of time complexity is \ (O (nT \ log n ) \) , where \ (T \) is the desired number of comparisons sense at random string two strings. But he notes that all the strings are seeking space will burst out, so directly on the original series sweep on the line. Is not only about zxythe iron Han Han will all sub-strings are seeking out pair of (

For all the data, we consider the process of comparing two strings lexicographic order, from front to back sweep two strings prefix, as long as a length such that two different character strings corresponding to the length, can be compared by the character two strings lexicographically, so we consider a different prefix find the first two strings. And the length of the prefix is ​​two points, that is, if a found varying lengths such that the length of the two strings prefix length, the first length different prefix length must not be greater than this, a different first or prefix length must be greater than this length.

Analyzing the two strings are the same prefix may be solved by HASH. This can be done time complexity \ (O (n \ log n \ log m) \) a, where \ (O (\ log m) \) is the complexity of two points.

As for how to find a good but nothing to do (because of the location and character requirements relating to the character sequence \ (ab \) and \ (ba \) different requirements related to the order, but as \ (abab \) , requires two characters before judge the same as the string that the composition of the two characters, and character position independent claim) of the hashfunction, the original string could hashagain, and then the difference of the original sequence hashagain, and then the original second-order differential string hashagain, has been hashdown Enough(

Code

(80 pts)

#include <cstdio>
#include <algorithm>

typedef long long int ll;

const int maxn = 50005;

int n, m, ans;
int v[maxn], w[maxn];
char S[maxn];

struct BIT {
  int A[maxn];

  inline int lowbit(const int x) { return x & -x; }

  inline void update(int x, const int v) { do A[x] += v; while ((x += lowbit(x)) <= n); }

  inline int query(int x) { int _ret = 0; do _ret += A[x]; while (x -= lowbit(x)); return _ret; }
};
BIT tree;

bool cmp(const int &a, const int &b);

int main() {
  freopen("sort.in", "r", stdin);
  freopen("sort.out", "w", stdout);
  scanf("%d %d\n%s", &n, &m, S + 1);
  for (int i = 1; i <= n; ++i) { v[i] = i; }
  std::sort(v + 1, v + 1 + n, cmp);
  for (int i = 1; i <= n; ++i) {
    w[v[i]] = i;
  }
  for (int i = 1; i <= n; ++i) {
    ans += tree.query(n) - tree.query(w[i]);
    tree.update(w[i], 1);
  }
  qw(ans, '\n', true);
  return 0;
}

inline bool cmp(const int &a, const int &b) {
  for (int len = 1, i = a, j = b; len <= m; ++i, ++j, ++len) {
    if ((i > n) || (j > n)) {
      return i > n;
    } else if (S[i] != S[j]) {
      return S[i] < S[j];
    }
  }
  return a < b;
}

(std)

#include <cstdio>

#define mo 1000000007
#define N 50055

int f[N],s[N],tmp[N],n,m,i,ch,ans;
long long hash[N],pow[N];

//二分+哈希求以i开头的和以j开头的两个子串哪个字典序更小
bool lessThanOrEqual(int i, int j)
{
    if (i == j) return true;
    int l, r, k;
    long long hsi, hsj;
    //二分求i和j开始从左向右第一位不同的位
    l = 0;
    r = m+1;
    if (n-j+2 < r) r = n-j+2;
    if (n-i+2 < r) r = n-i+2;
    while (r-l > 1)
    {
        k = (l+r)/2;
        //子串[i,i+k-1]的哈希值
        hsi = hash[i+k-1]-hash[i-1]*pow[k]%mo;
        if (hsi < 0) hsi += mo;
        //子串[j,j+k-1]的哈希值
        hsj = hash[j+k-1]-hash[j-1]*pow[k]%mo;
        if (hsj < 0) hsj += mo;
        if (hsi == hsj) l = k; else r = k;
    }
    //s[i+l]和s[j+l]是第一位不同的位
    if (l == m) return true;
    return s[i+l] < s[j+l];
}

//归并排序
void sort(int l, int r)
{
    if (l == r) return;
    int mi = (l+r)/2;
    sort(l, mi);
    sort(mi+1, r);
    int i=l, j=mi+1;
    int nt = l;
    while (i<=mi || j<=r)
    {
        bool ilej;
        if (i > mi) ilej = false;
        else
        if (j > r) ilej = true;
        else ilej = lessThanOrEqual(f[i],f[j]);
        if (ilej) tmp[nt++] = f[i++];
        else
        {
            tmp[nt++] = f[j++];
            //从右区间取数时,右区间和左区间之间产生了继续对
            //累加答案
            ans += mi-i+1;
        }
    }
    for (i=l; i<=r; ++i) f[i] = tmp[i];
}

int main()
{
    freopen("sort.in", "r", stdin);
    freopen("sort.out", "w", stdout);
    scanf("%d%d", &n, &m);
    hash[0] = 0;
    pow[0] = 1;
    for (i=1; i<=n; ++i)
    {
        for (ch=getchar(); ch<=32; ch=getchar());
        s[i] = ch-96;
        //预处理hash[i]=子串[1,i]的哈希值
        hash[i] = (hash[i-1]*29+s[i])%mo;
        //预处理pow[i]=29^i
        pow[i] = pow[i-1]*29%mo;
        f[i] = i;
    }
    s[n+1] = 0;
    sort(1, n);
    printf("%d\n", ans);
    return 0;
}

C Chocolate

There is divided into a \ (n \ times m \) lattice rectangular chocolate, although very regular in shape but the quality is not evenly distributed, each cell has its own weight \ (W_ {I, J} \) , with \ ( n \ times m \) positive integer. You will need to cut the block of chocolate \ (K \) pieces, each requirement is rectangular, and the weight thereof are \ (A_1 \ SIM a_k \) . A weight equal to the weight of the chocolate all the grid and it contains.

Cut chocolate, you can each selected from a large chocolate, along a horizontal or vertical line of the grid was cut into two small chocolate. Cut down the small piece of chocolate can continue cutting. Cutting path can not be a polyline or slash. Any time the current all chocolate must be rectangular.

For a given chocolate and segmentation requirements, you determine whether there is a cut solutions to meet the above requirements.

There \ (T \) set of data, the time limit \ (2S \) .

Limitations

img

Solution

Algorithm \(1\)

A judgment is equal to a combined \ (m \) , when the \ (W \) always equals \ (1 \) and only one line, as long as follow \ (a \) to a to a cut.

Can be tested point: \ (1 \) . Expected score \ (10 ~ pts \)

Algorithm \(2\)

Where blast search cut cut several times, each note will have a new cut a piece of chocolate is generated, so a maximum cut \ (K \) knives, and for each piece of chocolate, have only \ (O (n + m) \) species-cut method, and therefore the depth of the search tree is \ (K \) , each node has \ ((n + m) \ ) children. The complexity of the search for the burst \ (O (~ T (n-m +) ^ K) \) .

Test points by: \ (1, 2 ~, 3 ~, 4 ~ \) , the desired score \ (40 ~ pts \)

Algorithm \(3\)

Like zxythe iron daft as reading the wrong question, that each must be cut back to meet a \ (A \) , and then write a garbage burst search can be obtained \ (40 PTS \) .

Algorithm \(4\)

Note that \ (k \) is very small, and therefore very suitable for like pressure.

Set \ (f_ {i, j, x, y, S} \) is the upper left corner is \ ((I, J) \) , the lower right corner \ ((x, ~ y) \) rectangle satisfies \ (a \) in the state \ (S \) , the process moves as long as that knife where enumeration was cut to meet what the situation. Written note found very good writing.

Time complexity \ (O (m ^ 2 T ^ n-2 (n-m +). 3 ^ K) \) . Space complexity \ (O (n-2M ^ 2 ^ \ K ^ Times. 3) \) .

Test points by: \ (. 1 ~ \ SIM. 6 \) , the desired score \ (60 ~ pts \)

Algorithm \(5\)

It notes that the complexity of the bottlenecks in the number of states considered optimal state.

We found that for a determined rectangle top left and right, and if we determine it to be satisfied \ (a \) the sum, then his lower left and right can be determined. So we find that as long as the determined \ (i, ~ j, ~ x \) and \ (S \) , then the \ (Y \) can be determined, so when the search is rectangular and is not equal to \ (S \ ) state \ (a \) of the cut and a state, then the search to the number of states becomes \ (O (n-m ^ 2 \ 2 ^ K Times) \) .

So this time complexity \ (O (T \ ^ n-2 Times \ Times m \ Times (n-m +) \ K ^ Times. 3) \) .

Test points by: \ (. 1 ~ \ SIM. 8 \) , the desired score \ (PTS ~ 80 \) .

Algorithm \(6\)

For (w = 1 \) \ point, we note equivalent of taking some small rectangles makes up such a large rectangle. Since each of the small rectangle are identical, we do not need to specifically record the first few lines of the rectangular columns. Thus it may be provided \ (f_ {i, j, S} \) is the length \ (I \) , width \ (J \) rectangular, could spell state \ (S \) a \ (A \ ) , when the transfer can still enumerate how the knife is cut.

Time complexity \ (O (n-\ Times m \ Times (n-m +) \ K ^ Times. 3) \) .

Test points by: \ (1, 1-3, 1-5, 1-7, 1-9 \) , the desired score \ (PTS ~ 50 \) .

Algorithm \(7\)

Notes that at the time of the transfer, we have enumerated which transferred to the collection, then we no longer need to enumerate where the knife cut, and because a certain, both vertical and lateral cut up to only one knife method, where the specific cutting knife, this location can be binary. Such complexity is optimized to transfer to the \ (O (\ log m) \) . The total time complexity \ (O (n-m. 3 ^ 2 ^ K \ log m) \) . You can pass all the test points.

Expected score \ (100 PTS ~ \) .

Code

(80 points)

#include <cstdio>
#include <cstring>

typedef long long int ll;

const int maxn = 11;
const int maxt = 1030;

bool vis[maxn][maxn][maxn][maxn][maxt], frog[maxn][maxn][maxn][maxn][maxt];

int n, m, k, T;
int MU[maxn][maxn], A[maxn], sum[maxn][maxn], val[maxt];

void work();
void clear();
bool dfs(const int x, const int y, const int z, const int w, const int S);

int main() {
  freopen("chocolate.in", "r", stdin);
  freopen("chocolate.out", "w", stdout);
  qr(T);
  while (T--) {
    clear();
    work();
  }
  return 0;
}

void clear() {
  memset(A, 0, sizeof A);
  memset(MU, 0, sizeof MU);
  memset(val, 0, sizeof val);
  memset(vis, 0, sizeof vis);
  memset(sum, 0, sizeof sum);
  memset(frog, 0, sizeof frog);
  n = m = k = 0;
}

void work() {
  qr(n); qr(m); qr(k);
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
      qr(MU[i][j]);
      sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + MU[i][j];
    }
  }
  for (int i = 0; i < k; ++i) {
    qr(A[i]);
  }
  int ALL = (1 << k) - 1;
  for (int S = 1; S <= ALL; ++S) {
    for (int i = 0; i < k; ++i) if (S & (1 << i)) {
      val[S] += A[i];
    }
  }
  puts(dfs(1, 1, n, m, ALL) ? "yes" : "no");
}

bool dfs(const int x, const int y, const int z, const int w, const int S) {
  bool &thisv = vis[x][y][z][w][S], &thisf = frog[x][y][z][w][S];
  if (thisv) { return thisf; }
  thisv = true;
  if ((sum[z][w] - sum[x - 1][w] - sum[z][y - 1] + sum[x - 1][y - 1]) != val[S]) {
    return false;
  }
  if ((S & (S - 1)) == 0) {
    return thisf = true;
  }
  for (int i = x; i < z; ++i) {
    for (int S0 = S; S0; S0 = (S0 - 1) & S) if (dfs(x, y, i, w, S0) && dfs(i + 1, y, z, w, S ^ S0)) {
      return thisf = true;
    }
  }
  for (int i = y; i < w; ++i) {
    for (int S0 = S; S0; S0 = (S0 - 1) & S) if (dfs(x, y, z, i, S0) && dfs(x, i + 1, z, w, S ^ S0)) {
      return thisf = true;
    }
  }
  return false;
}

(std)

#include <cstdio>
#include <list>

#define MAXK 15
#define N 11

struct Quad
{
    int a, b, c, d;
    Quad(int _a, int _b, int _c, int _d): a(_a), b(_b), c(_c), d(_d) {}
};

std::list<Quad> lf, lfx, lfy;
char f[N][N][N][1<<MAXK],fx[N][N][N][1010],fy[N][N][N][1010];
int sumx[N][N][N],sumy[N][N][N],suma[1<<MAXK],bg[1<<MAXK],ed[1<<MAXK],c[15000000],e[MAXK+1],a[20],
    n,m,K,i,j,l,r,T,sta,nc,w;

/*
求:以j1为左边界、j2为右边界、i1为上边界的矩形中,下边界为多少的矩形
重量和是w。如果不存在则返回-1
用二分求
*/
int calcx(int j1, int j2, int i1, int w)
{
    // fx[j1][j2][i1][w]用于记录该子问题有没有被求结果
    // 已求结果则直接返回结果
    if (fx[j1][j2][i1][w] != 0) return fx[j1][j2][i1][w];
    // 未求结果,将该状态加入待清空队列
    lfx.push_back(Quad(j1,j2,i1,w));
    // 二分求i2的位置
    int l, r, k;
    l = i1-1;
    r = n+1;
    while (r-l > 1)
    {
        k = l+r>>1;
        if (sumx[j1][j2][k]-sumx[j1][j2][i1-1] <= w) l = k; else r = k;
    }
    if (sumx[j1][j2][l]-sumx[j1][j2][i1-1] != w) l = -1;
    return fx[j1][j2][i1][w]=l;
}

/*
求:以i1为上边界、i2为下边界、j1为左边界的矩形中,右边界为多少的矩形
重量和是w。如果不存在则返回-1
和上面对称
*/
int calcy(int i1, int i2, int j1, int w)
{
    if (fy[i1][i2][j1][w] != 0) return fy[i1][i2][j1][w];
    lfy.push_back(Quad(i1,i2,j1,w));
    int l, r, k;
    l = j1-1;
    r = m+1;
    while (r-l > 1)
    {
        k = l+r>>1;
        if (sumy[i1][i2][k]-sumy[i1][i2][j1-1] <= w) l = k; else r = k;
    }
    if (sumy[i1][i2][l]-sumy[i1][i2][j1-1] != w) l = -1;
    return fy[i1][i2][j1][w]=l;
}

/*
求(i1,j1)~(i2,j2)的矩形能否切出sta中的巧克力
*/
bool work(int i1, int i2, int j1, int j2, int sta)
{
    //记忆化:求过了则直接返回
    if (f[i1][i2][j1][sta] != 0) return f[i1][i2][j1][sta]==1;
    if (bg[sta] == ed[sta]) return true;
    //未求过,将该状态加入待清空队列
    lf.push_back(Quad(i1,i2,j1,sta));
    int i, sta2, x, y;
    //枚举sta的每个非空真子集
    for (i=bg[sta]; i<ed[sta]; ++i)
    {
        sta2 = c[i];
        
        //尝试横向切
        x = calcx(j1,j2,i1,suma[sta2]);
        if (x != -1)
        if (work(i1,x,j1,j2,sta2) && work(x+1,i2,j1,j2,sta-sta2))
        {
            f[i1][i2][j1][sta] = 1;
            return true;
        }
        
        //尝试纵向切
        y = calcy(i1,i2,j1,suma[sta2]);
        if (y != -1)
        if (work(i1,i2,j1,y,sta2) && work(i1,i2,y+1,j2,sta-sta2))
        {
            f[i1][i2][j1][sta] = 1;
            return true;
        }
    }
    f[i1][i2][j1][sta] = -1;
    return false;
}

void dfs(int sta, int t)
{
    if (t == MAXK)
    {
        if (sta > 0) c[nc++] = sta;
        return;
    }
    if (sta&e[t]) dfs(sta-e[t], t+1);
    dfs(sta, t+1);
}

int main()
{
    freopen("chocolate.in", "r", stdin);
    freopen("chocolate.out", "w", stdout);
    e[0] = 1; 
    for (i=1; i<=MAXK; ++i) e[i] = e[i-1]*2;
    
    //预处理每个sta有哪些非空真子集,连续存储在队列c中
    nc = 1;
    for (sta=1; sta<e[MAXK]; ++sta)
    {
        bg[sta] = nc; //bg表示sta的子集在c中的开头位置
        dfs(sta, 0); //dfs求sta的非空真子集
        --nc;
        ed[sta] = nc; //ed表示sta的子集在c中的结尾位置
    }
    
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d%d", &n, &m, &K);
        for (i=1; i<=n; ++i)
        for (j=1; j<=m; ++j)
        {
            scanf("%d", &w);
            //sumy[i][j][k]:从第i行到第j行,从第1列到第k列构成的矩形的重量和
            sumy[i][i][j] = sumy[i][i][j-1]+w;
            //sumx[i][j][k]:从第i列到第j列,从第1行到第k行构成的矩形的重量和
            sumx[j][j][i] = sumx[j][j][i-1]+w;
        }
        for (l=1; l<n; ++l)
        for (r=l+1; r<=n; ++r)
        for (j=1; j<=m; ++j) sumy[l][r][j] = sumy[l][r-1][j]+sumy[r][r][j];
        for (l=1; l<m; ++l)
        for (r=l+1; r<=m; ++r)
        for (i=1; i<=n; ++i) sumx[l][r][i] = sumx[l][r-1][i]+sumx[r][r][i];
        
        for (i=1; i<=K; ++i) scanf("%d", &a[i]);
        //求出{ai}的各个子集的重量和
        //suma[sta]:sta中的巧克力的总重量
        for (sta=0; sta<e[K]; ++sta)
        {
            suma[sta] = 0;
            for (i=sta, j=1; i>0; i>>=1, ++j)
            if (i&1) suma[sta] += a[j];
        }
        
        // 如果所有ai的总重量!=巧克力的总重量
        if (suma[e[K]-1] != sumy[1][n][m])
        {
            printf("no\n");
            continue;
        }
        
        //lf、lfx、lfy用于记录哪些状态被记忆化了,用于之后清零
        lf.clear();
        lfx.clear();
        lfy.clear();
        
        if (work(1,n,1,m,e[K]-1)) printf("yes\n");
        else printf("no\n");
        
        //清零记忆化过的状态
        for (std::list<Quad>::iterator it=lf.begin(); it!=lf.end(); ++it) f[it->a][it->b][it->c][it->d] = 0;
        for (std::list<Quad>::iterator it=lfx.begin(); it!=lfx.end(); ++it) fx[it->a][it->b][it->c][it->d] = 0;
        for (std::list<Quad>::iterator it=lfy.begin(); it!=lfy.end(); ++it) fy[it->a][it->b][it->c][it->d] = 0;
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/yifusuyi/p/11717173.html