华中校赛 14th

https://www.nowcoder.com/acm/contest/106#question

A

分类讨论

#include<bits/stdc++.h>
using namespace std ;
#define LL long long
int a[100010] ;
int d[100010] ;
vector< int > v[100010] ;
void dfs( int id , int fa , int c ){
    d[id] = c ;
    for( int i = 0 ; i < v[id].size() ; i++ ){
        if( v[id][i] == fa ) continue ;
        dfs( v[id][i] , id , 3 - c ) ;
    }
}
int main(){
    int T ;
    cin >> T ;
    while( T-- ){
          int n ;
          scanf( "%d" , &n ) ;
          for( int i = 1 ; i <= n ; i++ )
              v[i].clear() ;
          for( int i = 1 ; i <= n - 1 ; i++ ){
              int a , b ;
              scanf( "%d%d" , &a , &b ) ;
              v[a].push_back( b ) ;
              v[b].push_back( a ) ;
          }
          dfs( 1 , 0 , 1 ) ;
          LL b , w ;
          b = 0 ; w = 0 ;
          for( int i = 1 ; i <= n ; i++ )
              if ( d[i] == 1 ) b++ ;
              else w++ ;
          LL ans = 0 ;
          if ( n & 1 ) { ans = 2 * ( b * b * w + w * w * b ) ; }
          else{ ans = b * b * b + w * w * w + b * b * w + w * w * b ; }
          printf( "%lld\n" , ans ) ;
    }
    return 0 ;
}
View Code

B

等比数列

#include<bits/stdc++.h>
using namespace std ;
#define LL long long
char s[100010] ;
const LL mod = 1e9 + 7 ;
LL two[100010] ;
LL pow_mod( LL a , LL b ){
   a %= mod ;
   LL ans = 1 ;
   while( b ){
         if ( b & 1 ) { ans *= a ; ans %= mod ; }
         a *= a ; a %= mod ; b >>= 1 ;
   }
   return ans ;
}
LL inv_mod( LL x ){
   return pow_mod( x , mod - 2 ) ;
}
int main(){
    int k ;
    cin >> k ;
    scanf( "%s" , s ) ;
    two[0] = 1 ;
    for( int i = 1 ; i <= 100000 ; i++ ){
        two[i] = two[i - 1] * 2 ;
        two[i] %= mod ;
    }
    LL ans = 0 ;
    int len = strlen( s ) ;
    for( int i = 0 ; i < len ; i++ ){
        if ( s[i] == '0' || s[i] == '5' ){
            ans += two[i] ; ans %= mod ;
        }
    }
    LL q = two[len] ;
    if ( q == 1 ) { ans *= k ; ans %= mod ; }
    else{
         LL res = pow_mod( q , k ) ;
         res-- ; if ( res < 0 ) res += mod ;
         ans *= res ; ans %= mod ;
         q-- ; if ( q < 0 ) q += mod ;
         ans *= inv_mod( q ) ; ans %= mod ;
    }
    cout << ans << endl ;
    return 0 ;
}
View Code

C

并查集 (不带子树转移版)

有四种操作

1 u v 合并u,v所在的并查集

2 u  将u从其所在的并查集中分离出来

3 u 询问u所在并查集的大小

4 u v 询问u,v是否在一个并查集内

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define ALL(A) A.begin(), A.end()
#define sqr(x) ((x)*(x))
#define sc(x) scanf("%d", &x)
#define pr(x) printf(">>>"#x":%d\n", x)
#define fastio ios::sync_with_stdio(0),cin.tie(0)
#define frein freopen("in.txt", "r", stdin)
#define freout freopen("out.txt", "w", stdout)
#define debug cout<<">>>STOP"<<endl
template<class T> T gcd(T a, T b)
{
        if (!b)
        {
                return a;
        }
        return gcd(b, a % b);
}
const int maxn = 2e5 + 10;
int par[maxn], hs[maxn];
int sz[maxn];
int cnt;
void init(int n)
{
        for (int i = 0; i <= n; i++)
        {
                par[i] = i, hs[i] = i, sz[i] = 1;
        }
}
int find(int x)
{
        return par[x] == x ? x : par[x] = find(par[x]);
}
void unite(int x, int y)
{
        x = find(x);
        y = find(y);
        if (x != y)
        {
                par[x] = y, sz[y] += sz[x];
        }
}
void del(int x)
{
        sz[find(hs[x])]--;
        hs[x] = ++cnt;
}
int main()
{
        int T, kase = 1;
        sc(T);
        while (T--)
        {
                printf("Case #%d:\n", kase++);
                int n, q;
                sc(n);
                sc(q);
                init(n + q);
                cnt = n;
                for (int i = 0; i < q; i++)
                {
                        int op;
                        sc(op);
                        if (op == 1)
                        {
                                int u, v;
                                sc(u);
                                sc(v);
                                unite(hs[u], hs[v]);
                        }
                        else if (op == 2)
                        {
                                int u;
                                sc(u);
                                del(u);
                        }
                        else if (op == 3)
                        {
                                int u;
                                sc(u);
                                int ans = sz[find(hs[u])];
                                printf("%d\n", ans);
                        }
                        else
                        {
                                int u, v;
                                sc(u);
                                sc(v);
                                if (find(hs[u]) == find(hs[v]))
                                {
                                        printf("YES\n");
                                }
                                else
                                {
                                        printf("NO\n");
                                }
                        }
                }
        }
        return 0;
}
View Code

F

冒泡排序变种

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod = 1e9 + 9;
int num[100005];
int number[100005];
int visit[100005];
vector<int> now[100005];
int pop = 0;
int ans[100005];
int main()
{
        int n;
        int k;
        cin >> n >> k;
        int cur = 0;
        for (int i = 1; i <= n; i++)
        {
                scanf("%d", &num[i]);
                ans[i] = num[i];
        }
        sort(ans + 1, ans + 1 + n);
        if (k == 0)
        {
                for (int i = 1; i <= n; i++)
                {
                        if (num[i] != ans[i])
                        {
                                cout << i << endl;
                                return 0;
                        }
                }
                cout << -1 << endl;
                return 0;
        }
        for (int i = 1; i <= n; i++)
        {
                if (visit[i])
                {
                        continue;
                }
                ++pop;
                cur = 0;
                for (int j = i; j <= n; j += k)
                {
                        if (!visit[j])
                        {
                                now[pop].push_back(num[j]);
                                //cout<<num[j]<<" "<<j<<" ";
                        }
                }
                //cout<<endl;
                sort(now[pop].begin(), now[pop].end());
                for (int j = i; j <= n; j += k)
                {
                        if (!visit[j])
                        {
                                number[j] = now[pop][cur++];
                                visit[j] = 1;
                        }
                }
        }
        for (int i = 1; i <= n; i++)
        {
                if (number[i] != ans[i])
                {
                        cout << i << endl;
                        return 0;
                }
        }
        cout << -1 << endl;
        return 0;
}
View Code

G

反推是否符合垂心 重心 内心 外心

x=[0,0,0,0];
y=[0,0,0,0];
def dOt(x0,y0,x1,y1):
    return x0*x1+y0*y1;
 
def cRoss(x0,y0,x1,y1):
    return x0*y1-x1*y0;
 
def lEnth2(x,y):
    return x*x+y*y;
 
def check0():
    n=[0,0,0];
    for i in range(3):
        n[i]=cRoss(x[(i+1)%3]-x[i],y[(i+1)%3]-y[i],x[3]-x[i],y[3]-y[i]);
    if (n[0]<0 and n[1]<0 and n[2]<0) or (0<n[0] and 0<n[1] and 0<n[2]):
        return 1;
    else:
        return 0;
 
def check1():
    for i in range(3):
        if dOt(x[i]-x[3],y[i]-y[3],x[(i+2)%3]-x[(i+1)%3],y[(i+2)%3]-y[(i+1)%3])!=0:
            return 0;
    return 1
 
def check2():
    n=[0,0];
    for i in range(3):
        n[0]=abs(cRoss(x[(i+1)%3]-x[i],y[(i+1)%3]-y[i],x[3]-x[i],y[3]-y[i]));
        n[1]=abs(cRoss(x[(i+2)%3]-x[i],y[(i+2)%3]-y[i],x[3]-x[i],y[3]-y[i]));
        if n[0]!=n[1]:
            return 0;
    if check0()==1:
        return 1;
    else:
        return 0;
 
def check3():
    s=[0,0,0];
    l=[0,0,0];
    for i in range(3):
        s[i]=abs(cRoss(x[i]-x[3],y[i]-y[3],x[(i+1)%3]-x[3],y[(i+1)%3]-y[3]));
        l[i]=lEnth2(x[(i+1)%3]-x[i],y[(i+1)%3]-y[i]);
    for i in range(3):
        if s[i]*s[i]*l[(i+1)%3]!=s[(i+1)%3]*s[(i+1)%3]*l[i]:
            return 0;
    if check0()==1:
        return 1;
    else:
        return 0;
 
def check4():
    d=[0,0,0];
    for i in range(3):
        d[i]=lEnth2(x[i]-x[3],y[i]-y[3]);
    if d[0]!=d[1] or d[1]!=d[2] or d[2]!=d[0]:
        return 0;
    return 1
 
for i in range(4):
    x[i],y[i]=map(int,input().split());
if check1()==1 or check2()==1 or check3()==1 or check4()==1:
    print("Yes");
else:
    print("No");
View Code

I

单调队列 O(n)可以处理处每个点的贡献

注意在push的时候一侧要是严格的 另一侧要是不严格的 比如先>= 后> 因为这样才是全部情况 如果全是严格则缺少情况 全是不严格则有重复情况

(即一个区间应只有一个最大值最小值有贡献 如果有多个最大值最小值也只能算一次)

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn = 1000000 + 50;
int a[maxn], l[maxn], r[maxn];
inline void scan(int &a)
{
        a = 0;
        char c;
        while (c = getchar(), !isdigit(c));
        a = c - '0';
        while (c = getchar(), isdigit(c))
        {
                a = a * 10 + c - '0';
        }
}
int main()
{
        int n;
        while (scanf("%d", &n) != EOF)
        {
                LL res = 0;
                for (int i = 1; i <= n; i++)
                {
                        scanf("%d", &a[i]);
                }
                for (int i = 1; i <= n; i++)
                {
                        l[i] = r[i] = i;
                }
                for (int i = 2; i <= n; i++)
                {
                        int cur = i;
                        while (cur > 1 && a[i] >= a[cur - 1])
                        {
                                cur = l[cur - 1];
                        }
                        l[i] = cur;
                }
                for (int i = n - 1; i >= 1; i--)
                {
                        int cur = i;
                        while (cur < n && a[i] > a[cur + 1])
                        {
                                cur = r[cur + 1];
                        }
                        r[i] = cur;
                }
                for (int i = 1; i <= n; i++)
                {
                        res += (LL)a[i] * (LL)(i - l[i] + 1) * (LL)(r[i] - i + 1);
                }
                for (int i = 1; i <= n; i++)
                {
                        l[i] = r[i] = i;
                }
                for (int i = 2; i <= n; i++)
                {
                        int cur = i;
                        while (cur > 1 && a[i] <= a[cur - 1])
                        {
                                cur = l[cur - 1];
                        }
                        l[i] = cur;
                }
                for (int i = n - 1; i >= 1; i--)
                {
                        int cur = i;
                        while (cur < n && a[i] < a[cur + 1])
                        {
                                cur = r[cur + 1];
                        }
                        r[i] = cur;
                }
                for (int i = 1; i <= n; i++)
                {
                        res -= (LL)a[i] * (LL)(i - l[i] + 1) * (LL)(r[i] - i + 1);
                }
                printf("%lld\n", res);
        }
        return 0;
}
View Code

J

BFS

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod = 1e9 + 9;
int dp[1000005];
void init()
{
        dp[1] = 1, dp[2] = 1;
        for (int i = 3; i <= 1000000; i++)
        {
                dp[i] = dp[i - (i & (-i))] + 1;
        }
}
int visit[1000005];
queue<pair<int, int> > que;
int main()
{
        init();
        int a, b;
        cin >> a >> b;
        int anser = INT_MAX;
        que.push(make_pair(a, 0));
        while (!que.empty())
        {
                int now = que.front().first;
                visit[now] = 1;
                int cur = que.front().second;
                //cout<<now<<" "<<cur<<endl;
                que.pop();
                if (now == b)
                {
                        cout << cur << endl;
                        return 0;
                }
                if (!visit[now - 1])
                {
                        que.push(make_pair(now - 1, cur + 1));
                        visit[now - 1] = 1;
                }
                if (!visit[now + 1])
                {
                        que.push(make_pair(now + 1, cur + 1));
                        visit[now + 1] = 1;
                }
                if (!visit[now + dp[now]])
                {
                        que.push(make_pair(now + dp[now], cur + 1));
                        visit[now + dp[now]] = 1;
                }
                if (!visit[now - dp[now]])
                {
                        que.push(make_pair(now - dp[now], cur + 1));
                        visit[now - dp[now]] = 1;
                }
        }
        return 0;
}
View Code

K

二分答案

#include<bits/stdc++.h>
using namespace std ;
int a[100010] ;
#define LL long long
int main(){
    int n , k ;
    cin >> n >> k ;
    for( int i = 1 ; i <= n - 1 ; i++ )
        scanf( "%d" , &a[i] ) ;
    LL l , r ;
    l = 0 ; r = 1e11 ;
    while( l + 1 < r ){
          LL mid = ( l + r ) >> 1 ;
          LL sum = 0 ;
          int cnt = 1 ;
          for( int i = 1 ; i <= n - 1 ; i++ ){
              if ( a[i] > mid ) { cnt += 0x3f3f3f3f ; break ; }
              sum += a[i] ;
              if ( sum > mid ){
                  cnt++ ; sum = a[i] ;
              }
          }
          if ( cnt > k ) l = mid ;
          else r = mid ;
    }
    cout << r << endl ;
    return 0 ;
}
View Code

L

倒着搜索

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 2e3 + 10;
const int maxm = 1e5 + 10;
struct coord
{
        int x, y;
} tmp, nxt;
queue<coord>q;
int T, m, res;
int x[maxm], y[maxm], ans[maxn];
int state[maxn][maxn];
int dir[4][2] = {{0, -1}, {0, 1}, { -1, 0}, {1, 0}};
void bfs(int x, int y)
{
        state[tmp.x = x][tmp.y = y] = 2; //给所有大空地的地方打上标记 相当于并查集
        res--, q.push(tmp);  //剩下的数目-1 进行BFS
        while (!q.empty())
        {
                tmp = q.front();
                q.pop();
                for (int i = 0; i < 4; i++)
                {
                        nxt.x = tmp.x + dir[i][0]; //目标点的横纵坐标
                        nxt.y = tmp.y + dir[i][1];
                        if (nxt.x < 0 || nxt.x > 2000 || nxt.y < 0 || nxt.y > 2000) //如果这个点不符合条件
                        {
                                continue;
                        }
                        if (state[nxt.x][nxt.y] != 0) //如果这个点是树
                        {
                                continue;
                        }
                        state[nxt.x][nxt.y] = 2;
                        res--;
                        q.push(nxt);
                }
        }
}
bool check(int x, int y)
{
        for (int i = 0; i < 4; i++)
        {
                int xx = x + dir[i][0], yy = y + dir[i][1];
                if (xx < 0 || xx > 2000 || yy < 0 || yy > 2000)
                {
                        continue;
                }
                if (state[xx][yy] == 2)
                {
                        return 1;
                }
        }
        return 0;
}
int main()
{
        scanf("%d", &m);
        for (int i = 1; i <= m; i++)
        {
                scanf("%d%d", &x[i], &y[i]);
                x[i] += 1000, y[i] += 1000;  //避免负数 往右下移动1000
                state[x[i]][y[i]] = 1;  //表示该坐标是树
        }
        res = 2001 * 2001 - m;  //减去2001*2001剩下的不是树的点
        bfs(0, 0);  //减去所有没有被树包围的点
        for (int i = m; i; i--)
        {
                ans[i] = res++;
                state[x[i]][y[i]] = 0;
                if (check(x[i], y[i])) //如果这个树的四连通块有一个属于大空地 就把这个树连通的连通块全部BFS成大空地
                {
                        bfs(x[i], y[i]);
                }
        }
        for (int i = 1; i <= m; i++)
        {
                printf("%d\n", ans[i]);
        }
        return 0;
}
View Code

 

posted @ 2018-04-29 21:05  Aragaki  阅读(182)  评论(0编辑  收藏  举报