2019暑期多校


咕值詳見去年多校

牛客

2019牛客暑期多校訓練營(第一場)

題號 標題 團隊的狀態
A Equivalent Prefixes  通過
B Integration  通過
C Euclidean Distance  通過
D Parity of Tuples 未通過
E ABBA  通過
F Random Point in Triangle  通過
G Substrings 2 未通過
H XOR  通過
I Points Division  通過
J Fraction Comparision  通過

A

思路:二分+單調棧

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
int n, a[N], b[N], la[N], ra[N],lb[N], rb[N];
stack<int> st;
inline bool ck(int m) {
    while(!st.empty()) st.pop();
    st.push(0);
    for (int i = 1; i <= m; ++i) {
        while(!st.size() > 1 && a[st.top()] > a[i]) st.pop();
        la[i] = st.top();
        st.push(i);
    }
    while(!st.empty()) st.pop();
    st.push(m+1);
    for (int i = m; i >= 1; --i) {
        while(st.size() > 1 && a[st.top()] > a[i]) st.pop();
        ra[i] = st.top();
        st.push(i);
    }
 
    while(!st.empty()) st.pop();
    st.push(0);
    for (int i = 1; i <= m; ++i) {
        while(!st.size() > 1 && b[st.top()] > b[i]) st.pop();
        lb[i] = st.top();
        st.push(i);
    }
    while(!st.empty()) st.pop();
    st.push(m+1);
    for (int i = m; i >= 1; --i) {
        while(st.size() > 1 && b[st.top()] > b[i]) st.pop();
        rb[i] = st.top();
        st.push(i);
    }
    for (int i = 1; i <= m; ++i) if(la[i] != lb[i] || ra[i] != rb[i]) return false;
    return true;
}
int main() {
    while(~scanf("%d", &n)) {
        for (int i = 1;  i <= n; ++i) scanf("%d", &a[i]);
        for (int i = 1;  i <= n; ++i) scanf("%d", &b[i]);
        int l = 1, r = n, m = l+r+1 >>1;
        while( l < r) {
            if(ck(m)) l = m;
            else r = m-1;
            m = l+r+1>>1;
        }
        printf("%d\n", m);
    }
    return 0;
}
View Code

B

思路:裂項,詳見D神博客

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e3 + 5;
const int MOD = 1e9 + 7;
int a[N], n;
LL q_pow(LL n, LL k) {
    LL ans = 1;
    while(k){
        if(k&1) ans = (ans * n) % MOD;
        n =(n * n) % MOD;
        k >>= 1;
    }
    return ans;
}
int main() {
    while(~scanf("%d", &n)) {
        for (int i = 1; i <= n; ++i) scanf("%d",&a[i]);
        LL ans = 0;
        for (int i = 1; i <= n; ++i) {
            LL tmp = 2*a[i]%MOD;
            for (int j = 1; j <= n; ++j) {
                if(i == j) continue;
                tmp = (tmp * (a[j]*1LL*a[j]%MOD-a[i]*1LL*a[i]%MOD))%MOD;
            }
            ans = (ans + q_pow(tmp, MOD-2))%MOD;
        }
        printf("%lld\n", (ans+MOD)%MOD);
    }
    return 0;
}
View Code

C

思路:貪心,從大到小推平。詳見大佬博客

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e4 + 5;
int a[N], sum[N], n, m;
int main() {
    while(~scanf("%d %d", &n, &m)) {
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        sort(a+1, a+1+n, greater<int>());
        for (int i = 1; i <= n; ++i) sum[i] = sum[i-1]+a[i];
        int pos = n+1;
        LL x=0, y=0;
        for (int i = 1; i <= n; ++i){
            if(sum[i]-a[i]*i <= m) {
                x = (sum[i]-m)*1LL*(sum[i]-m)*i;
                y = i*i;
            }
            else {
                pos = i;
                break;
            }
        }
        for (int i = pos; i <= n; ++i) x += a[i]*1LL*a[i]*y;
        y *= m*m;
        LL d = __gcd(x, y);
        if(d) x /= d, y /= d;
        if(x == 0) printf("0\n");
        else if(y == 1) printf("%lld\n", x);
        else printf("%lld/%lld\n", x, y);
    }
    return 0;
}
View Code

D

E

思路:dp,保證A和B的差值在$-m$到$+n$之間

代碼:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
 
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
 
const int mod = 1e9+7;
 
/**********showtime************/
            const int maxn = 8e3+9;
            ll dp[maxn][maxn];
            int g(int x) {
                return x + 4000;
            }
int main(){
            int n,m;
            while(~scanf("%d%d", &n, &m)) {
                int s = 2 * (n + m);
                int t = (n + m);
                for(int i=0; i<=s; i++) {
                    for(int j=-t; j<=t; j++) {
                        dp[i][g(j)] = 0;
                    }
                }
 
                dp[0][g(0)] = 1;
 
                for(int i=1; i<=s; i++) {
                    for(int j=-t; j<=t; j++) {
                        if(j <= n)
                            dp[i][g(j)] = (dp[i][g(j)] + dp[i-1][g(j-1)] ) %mod;
                        if(j >= -m)
                            dp[i][g(j)] = (dp[i][g(j)] + dp[i-1][g(j+1)] ) %mod;
                    }
                }
//                cout<<dp[s][g(0)]<<endl;
                printf("%lld\n", dp[s][g(0)]);
            }
            return 0;
}
View Code

F

思路:

$\frac{22*s}{36}$

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
 
struct Point  {   // double pan duan
    ll  x,y;
    Point(ll a=0,ll b=0) { x=a;y=b; };
};
typedef Point Vector;
Vector operator + (Vector A, Vector B){ return Vector(A.x+B.x, A.y+B.y); } // 向量相加
Vector operator - (Point  A, Point  B){ return Vector(A.x-B.x, A.y-B.y); } // 向量生成
double operator * (Vector A, Vector B){ return A.x*B.x-A.y*B.y;          } // 點積
double operator ^ (Vector A, Vector B){ return A.x*B.y-A.y*B.x;          } // 叉積
ll Cross(Vector A, Vector B)        { return A.x*B.y - A.y*B.x;                             }  // 叉積
ll Area2(Point A, Point B, Point C) { return Cross(B-A, C-A);                               }  // 四邊形面積
int main(){
   Point a,b,c;
   while(~scanf("%lld %lld %lld %lld %lld %lld",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y)){
      ll area=abs(Cross(b-a,c-a) ) *11;
      printf("%lld\n",area);
   }
}
View Code

G

H

思路:線性基。

先將問題轉換成包含某個元素的異或起來為0的集合個數和

首先,先選出一組基(假設大小為$r$),那么對於非基元素的任意組合都可由基線性表示,也就是說對於每個非基元素,有$2^{n-r-1}$個包含它的集合滿足題意,

這部分貢獻是$(n-r)*2^{n-r-1}$。

然后考慮包含基元素的滿足題意的集合個數,對於某個基元素,將剩下的$n-1$個元素構成一組基,看能不能線性表示出它,如果能,包含這個基元素的集合個數是$2^{剩下元素個數}$

對於第二種情況可以先處理出非基元素的一組基。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
const int MOD = 1e9 + 7;
int n;
LL a[N];
vector<LL> s, b, other, B; 
LL q_pow(LL n, LL k) {
    if(k < 0) return 0;
    LL res = 1;
    while(k) {
        if(k&1) res = (res*n)%MOD;
        n = (n*n)%MOD;
        k >>= 1;
    }
    return res;
}
int main() {
    while(~scanf("%d", &n)) {
        s.clear();b.clear();other.clear();B.clear();
        for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
        for (int i = 1; i <= n; ++i) {
            LL t = a[i];
            for (LL x : b) {
                if((t^x) < t) t ^= x;
            }
            if(t) b.pb(t), s.pb(a[i]);
            else other.pb(a[i]);
        } 
        int sz = b.size();
        LL ans = (n-sz)*q_pow(2, n-sz-1)%MOD;
        for (LL x : other) {
            for (LL t : B) {
                if((x^t) < x) x ^= t;
            }
            if(x) B.pb(x);
        }
        for (LL x : s) {
            vector<LL> tb = B;
            for (LL t : s) {
                if(t != x) {
                    for (LL y : tb) {
                        if((y^t) < t) t ^= y;
                    }
                    if(t) tb.pb(t);
                }
            }
            for (LL t : tb) {
                if((x^t) < x) x ^= t;
            }
            if(!x) ans = (ans + q_pow(2, n-tb.size()-1))%MOD;
        }
        printf("%lld\n", ans);
    }
    return 0;
} 
View Code

I

思路:線段樹優化dp。

首先根據題意,A和B集合的分界線肯定是一橫一豎交替出現的折線。那么考慮以每個點i為折線的轉折點時的dp[i]。用線段樹維護之前轉折點的最大值並更新以當前點為轉折點的最大值。

對於每個點i,它對y值為[0, a[i].y-1]轉折點的貢獻為a,對y值為[a[i].y+1,len]轉折點的貢獻為b。因為a集合在上,b集合在下。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
struct Node {
    int x, y, a, b;
    bool operator < (const Node & rhs) const {
        if(x == rhs.x) return y > rhs.y;
        else return x < rhs.x;
    }
}a[N];
int n;
vector<int> vc;
LL mx[N<<2], lazy[N<<2];
inline void push_up(int rt) {
    mx[rt] = max(mx[rt<<1], mx[rt<<1|1]);
}
inline void push_down(int rt) {
    lazy[rt<<1] += lazy[rt];
    lazy[rt<<1|1] += lazy[rt];
    mx[rt<<1] += lazy[rt];
    mx[rt<<1|1] += lazy[rt];
    lazy[rt] = 0;
}
void build(int rt, int l, int r) {
    mx[rt] = lazy[rt] = 0;
    if(l == r) return ;
    int m = l+r >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
void update(int p, LL v, int rt, int l, int r) {
    if(l == r){
        mx[rt] = v;
        return ;
    }
    int m = l+r >> 1;
    if(lazy[rt]) push_down(rt);
    if(p <= m) update(p, v, ls);
    else update(p, v, rs);
    push_up(rt);
}
void Update(int L, int R, int v, int rt, int l, int r) {
    if(L > R) return ;
    if(L <= l && r <= R) {
        mx[rt] += v;
        lazy[rt] += v;
        return ;
    }
    int m = l+r >> 1;
    if(lazy[rt]) push_down(rt);
    if(L <= m) Update(L, R, v, ls);
    if(R > m)  Update(L, R, v, rs);
    push_up(rt);
}
LL query(int L, int R, int rt, int l, int r){
    if(L > R) return 0;
    if(L <= l && r <= R) return mx[rt];
    int m = l+r >> 1;
    if(lazy[rt]) push_down(rt);
    LL ans = 0;
    if(L <= m) ans = max(ans, query(L, R, ls));
    if(R > m) ans = max(ans, query(L, R, rs));
    push_up(rt);
    return ans;
}
int main() {
    while(~scanf("%d", &n)) {
        vc.clear();
        for (int i = 1; i <= n; ++i) scanf("%d %d %d %d",&a[i].x, &a[i].y, &a[i].a, &a[i].b), vc.pb(a[i].y);
        sort(vc.begin(), vc.end());
        vc.erase(unique(vc.begin(), vc.end()), vc.end());
        for (int i = 1; i <= n; ++i) a[i].y = lower_bound(vc.begin(), vc.end(), a[i].y)-vc.begin()+1;
        sort(a+1, a+1+n);
        int l = vc.size();
        ++l;
        build(1, 0, l);
        for (int i = 1; i <= n; ++i) {
            LL tmp = query(0, a[i].y, 1, 0, l);
            update(a[i].y, tmp+a[i].b, 1, 0, l);
            Update(0, a[i].y-1, a[i].a, 1, 0, l);
            Update(a[i].y+1, l, a[i].b, 1, 0, l);
        }
        printf("%lld\n", mx[1]);
    }
    return 0;
}
/*
3
1 1 10 1
8 9 10 1
5 4 10 1
*/
View Code

J

思路:大數過

import java.math.BigInteger;
import java.util.*;
 
public class Main {
 
    /**
     * @param args
     */
     
    public static void main(String[] args) {
            BigInteger x, a, y, b;
            Scanner reader = new Scanner(System.in);
            while(reader.hasNext()) {
                x = reader.nextBigInteger();
                a = reader.nextBigInteger();
                y = reader.nextBigInteger();
                b = reader.nextBigInteger();
                if(x.multiply(b).compareTo(y.multiply(a)) == 0) {
                    System.out.println("=");
                }
                else if(x.multiply(b).compareTo(y.multiply(a)) > 0)  {
                    System.out.println(">");
                }
                else {
                    System.out.println("<");
                }
            }
                 
        }
 
}
View Code

2019牛客暑期多校訓練營(第二場)

題號 標題 團隊的狀態
A Eddy Walker  通過
B Eddy Walker 2  通過
C Go on Strike! 未通過
D Kth Minimum Clique  通過
E MAZE  通過
F Partition problem  通過
G Polygons  通過
H Second Large Rectangle  通過
I Inside A Rectangle 未通過
J Subarray  通過

A

思路:蒙特卡洛一下,就能找到規律,除了0這個點,其他點的概率是$\frac{1}{n-1}$,隊友讀了題居然沒跟我說題意,血虧。

以n=10為例,打表代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back

int  a[10];
int main() {
    mt19937 mt_rand(time(NULL));
    for (int i = 1; i <= 100000; ++i) {
        int st = 0;
        int up = 1<<10, s = 1;
        while(true) {
            if(mt_rand()%2 == 0) st = (st+9)%10;
            else st = (st+1)%10;
            s |= 1<< st;
            if(s == up-1) {
                a[st]++;
                break;
            }
        }
    }
    for (int i = 0; i < 10; ++i) printf("%d %.10f\n", i, a[i]*1.0/100000);
    return 0;
}
View Code

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
 
const int MOD = 1e9 + 7;
int T, m, n;
LL q_pow(LL n, LL k) {
    LL res = 1;
    while(k) {
        if(k&1) res = (res*n) % MOD;
        n = (n * n)%MOD;
        k >>= 1;
    }
    return res;
}
int main() {
    scanf("%d", &T);
    LL res = 1;
    while(T--) {
        scanf("%d %d", &n, &m);
        if(n == 1) ;
        else if(m) (res *= q_pow(n-1, MOD-2)) %= MOD;
        else res *= 0;
        printf("%lld\n", res);
    }
    return 0;
}
View Code

B

思路:容易發現是個線性遞推式,因為系數$\frac{1}{k}$是個常數。於是可以打出前2*k項,扔進杜教BM板子里就能求出第$n$項。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
 
const int mod = 1e9 + 7;
const int MOD = 1e9 + 7;
ll q_pow(ll n, ll k) {
    ll res = 1;
    while(k) {
        if(k&1) res = (res*n)%mod;
        n = (n*n)%mod;
        k >>= 1;
    }
    return res;
}
 
namespace linear_seq {
    const int N=10010;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define mp make_pair
    #define all(x) (x).begin(),(x).end()
    #define SZ(x) ((int)(x).size())
    typedef vector<ll> VI;
    typedef pair<ll,ll> PII;
    ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
    ll res[N],base[N],_c[N],_md[N];
    vector<ll> Md;
    void mul(ll *a,ll *b,int k) {
        rep(i,0,k+k) _c[i]=0;
        rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
        for (int i=k+k-1;i>=k;i--) if (_c[i])
            rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
        rep(i,0,k) a[i]=_c[i];
    }
    ll solve(ll n,VI a,VI b) { // a 系數 b 初值 b[n+1]=a[0]*b[n]+...
//        printf("%d\n",SZ(b));
        ll ans=0,pnt=0;
        int k=SZ(a);
        assert(SZ(a)==SZ(b));
        rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
        Md.clear();
        rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
        rep(i,0,k) res[i]=base[i]=0;
        res[0]=1;
        while ((1ll<<pnt)<=n) pnt++;
        for (int p=pnt;p>=0;p--) {
            mul(res,res,k);
            if ((n>>p)&1) {
                for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
                rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
            }
        }
        rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
        if (ans<0) ans+=mod;
        return ans;
    }
    VI BM(VI s) {
        VI C(1,1),B(1,1);
        int L=0,m=1,b=1;
        rep(n,0,SZ(s)) {
            ll d=0;
            rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
            if (d==0) ++m;
            else if (2*L<=n) {
                VI T=C;
                ll c=mod-d*powmod(b,mod-2)%mod;
                while (SZ(C)<SZ(B)+m) C.pb(0);
                rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                L=n+1-L; B=T; b=d; m=1;
            } else {
                ll c=mod-d*powmod(b,mod-2)%mod;
                while (SZ(C)<SZ(B)+m) C.pb(0);
                rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                ++m;
            }
        }
        return C;
    }
    ll gao(VI a,ll n) {
        VI c=BM(a);
        c.erase(c.begin());
        rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
        return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
    }
};
int k, T;
ll n;
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %lld", &k, &n);
        vector<ll> vc;
        if(n == -1) printf("%lld\n", 2*q_pow(k+1, MOD-2)%MOD);
        else {
            vc.pb(1);
            for (int i = 1; i <= 2*k; ++i) {
                ll tmp = 0;
                for (int j = max(0, i-k); j < i; ++j){
                    (tmp += vc[j]) %= MOD;
                }
                (tmp *= q_pow(k, MOD-2)) %= MOD;
                vc.pb(tmp);
            }
            printf("%lld\n", linear_seq::gao(vc, n));
        }
    }
    return 0;
}
View Code

C

D

思路:

既然要選擇第K小的,我們可以從小到大做。每次通過最小的一個最小團擴展,可以利用bitset優化判斷擴展的可行性。利用優先隊列,從其中取出的第k個就是答案。

隊友代碼:

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
 
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
 
const int mod = 1e9+7;
 
/**********showtime************/
 
            const int maxn = 109;
            char str[maxn];
            struct node{
                ll val;
                bitset<109>bs;
                bool operator<(const node & o) const{
                    return val > o.val;
                }
            }a[maxn];
int main(){
            int n,k;
            scanf("%d%d", &n, &k);
            for(int i=1; i<=n; i++) {
                scanf("%lld", &a[i].val);
            }
            for(int i=1; i<=n; i++) {
                scanf("%s", str+1);
                for(int j=1; j<=n; j++) {
                    if(str[j] == '1')a[i].bs.set(j);
                }
            } 
 
            priority_queue<node>que;
            node s;
            s.val = 0;
            s.bs.reset();
            que.push(s);
            int flag = 0;ll res;
            while(!que.empty()) {
                node u = que.top();
                que.pop();
                k -- ;
                if(k == 0) {
                    flag = 1;
                    res = u.val;
                    break;
                }
                int mx = 1;
                for(int i=1; i<=n; i++) {
                    if(u.bs[i] == 1) mx = i + 1;
                }
 
                for(int i=mx; i<=n; i++) {
                    if((u.bs & a[i].bs) == u.bs) {
                        u.bs.set(i);    u.val += a[i].val;
                        que.push(u);
                        u.bs.reset(i);    u.val -= a[i].val;
                    }
                }
            }
            if(flag) printf("%lld\n", res);
            else puts("-1");
            return 0;
}
View Code

E

思路:

考慮從第$i$行到第$i+1$行的轉移,假設第$i$行為"10010"

設 $dp_{i,j}$表示到第$i$行第$j$列的方案數。

於是相鄰兩項dp的轉移過程可以看成一個矩陣乘以一個向量(如果暫時不考慮當前行的橫向轉移)。 多項之間的轉移可以看成矩陣連乘再乘以一個向量。

於是用線段樹維護矩陣的乘法,線段樹每個葉子節點表示一個矩陣。 單次修改復雜度O($log(n)m^3$),其中$m^3$是矩陣乘法的復雜度。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 5e4 + 5;
const int MOD = 1e9 + 7;
int n, q, m, op, x, y;
string b[N];
struct Matrix {
    int a[10][10];
    inline void init() {memset(a, 0, sizeof a);}
    inline void _init() {
        init();
        for (int i = 0; i < m; ++i) a[i][i] = 1;
    }
    inline void reset(int p) {
        init();
        for (int i = 0; i < m; ++i) {
            for (int j = i; j >= 0; --j) if(b[p][j] == '0') a[j][i] = 1; else break;
            for (int j = i; j < m; ++j) if(b[p][j] == '0') a[j][i] = 1; else break;
        }
    }
    inline Matrix operator * (const Matrix & rhs) const {
        Matrix res;
        res.init();
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < m; ++j) {
                if(a[i][j]) {
                    for (int k = 0; k < m; ++k) (res.a[i][k] += a[i][j]*1LL*rhs.a[j][k]%MOD) %= MOD;
                }
            }
        }
        return res;
    }
}tree[N<<2];
inline void push_up(int rt) {
    tree[rt] = tree[rt<<1]*tree[rt<<1|1];
}
void build(int rt, int l, int r) {
    if(l == r) {
        tree[rt].reset(l);
        return ;
    }
    int m = l+r >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
void update(int p, int rt, int l, int r) {
    if(l == r) {
        tree[rt].reset(l);
        return ;
    }
    int m = l+r >> 1;
    if(p <= m) update(p, ls);
    else update(p, rs);
    push_up(rt);
}
 
int main(){
    fio;
    cin >> n >> m >> q;
    for (int i = 1; i <= n; ++i) cin >> b[i];
    build(1, 1, n);
    while(q--) {
        cin >> op >> x >> y;
        if(op == 1) {
            if(b[x][y-1] == '1') b[x][y-1] = '0'; else b[x][y-1] = '1';
            update(x, 1, 1, n);
        }
        else {
            cout << tree[1].a[x-1][y-1] << "\n";
        }
    }
    return 0;
}
View Code

F

思路:折半枚舉,對於每一半的每個狀態記錄每一行狀態為1的行和,最后暴力更新答案。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
const int manx=1e6+10;
int n;
int a[30][30];
LL mp[(1<<15)][30];
LL mq[(1<<15)][30];
vector<int> vc[18];
int main(){
    scanf("%d",&n);
    for(int i=0;i<2*n;i++){
        for(int j=0;j<2*n;j++){
            scanf("%d",&a[i][j]);
        }
    }
    int up = 1<<n;
    for(int i=0;i<up;i++){
        for(int j=0;j<n;j++){
            if(i&(1<<j)){
                for (int k = 0; k < 2*n; ++k) {
                    mp[i][k] += a[k][j];
                }
            }
        }
    }
    for(int i=0;i<up;i++){
        for(int j=0;j<n;j++){
            if(i&(1<<j)){
                for (int k = 0; k < 2*n; ++k) {
                    mq[i][k] += a[k][j+n];
                }
            }
        }
        vc[n-__builtin_popcount(i)].pb(i);
    }
    LL ans = 0;
    for (int i = 0; i < up; ++i) {
        int x = __builtin_popcount(i);
        for (int j : vc[x]){
            LL t = 0;
            for (int k = 0; k < n; ++k) {
                if((i&(1<<k)) == 0) t += mp[i][k]+mq[j][k];
                if((j&(1<<k)) == 0) t += mp[i][n+k]+mq[j][n+k];
            }
            ans = max(ans, t);
        }
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

G

思路:平面直線圖模板題。

H

思路:將每個最大面積和次大面積的左上角扔進map里去重。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e3 + 5;
int l[N][N], r[N][N], up[N][N], a[N][N], n, m;
char s[N][N];
map<int, vector<pii>, greater<int>> mp;
int main() {
    scanf("%d %d",&n, &m);
    for (int i = 1; i <= n; ++i) scanf("%s", s[i]+1);
    for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) a[i][j] = s[i][j]-'0';
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if(a[i][j]) l[i][j] = l[i][j-1]+1;
        }
        for (int j = m; j >= 1; --j) {
            if(a[i][j]) r[i][j] = r[i][j+1]+1;
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if(a[i][j]) {
                up[i][j] = up[i-1][j]+1;
                if(a[i-1][j]) {
                    l[i][j] = min(l[i-1][j], l[i][j]);
                    r[i][j] = min(r[i-1][j], r[i][j]);
                }
                int A = up[i][j], B = r[i][j]+l[i][j]-1;
                mp[A*B].pb(i-up[i][j]+1, j-l[i][j]+1);
                mp[A*(B-1)].pb(i-up[i][j]+1, j-l[i][j]+1);
                mp[(A-1)*B].pb(i-up[i][j]+1, j-l[i][j]+1);
            }
        }
    }
    int t = 0;
    for (auto &it : mp) {
        sort(it.se.begin(), it.se.end());
        it.se.erase(unique(it.se.begin(), it.se.end()), it.se.end());
        for (int i = 0; i < it.se.size(); ++i) {
            ++t;
            if(t == 2) {
                printf("%d\n", it.fi);
                return 0;
            }
        }
    }
    printf("0\n");
    return 0;
}
View Code

I

J

思路:將每個答案的區間包含的點扣出來然后求前綴和,詳見隊友博客

隊友代碼:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;


template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

/**********showtime************/
            const int maxm = 2e7+9;
            const int maxn = 1e6+9;
            int le[maxn],ri[maxn];
            int lto[maxn],rto[maxn];
            ll f[maxm];
            int g(int x) {
                return x + 10000000;
            }
int main(){
            int n;
            scanf("%d", &n);

            for(int i=1; i<=n; i++) scanf("%d%d", &le[i], &ri[i]);

            int sum = 0;
            /// 向右擴展
            le[n+1] = 1000000000;
            for(int i=1; i<=n; i++) {
                sum += ri[i] - le[i] + 1;
                rto[i] = min(sum, le[i+1] - ri[i] - 1);
                sum -= le[i+1] - ri[i] - 1;
                if(sum < 0) sum = 0;
            }
            /// 向左擴展
            sum = 0;
            ri[0] = -1;

            for(int i=n; i>=1; i--) {
                sum += ri[i] - le[i] + 1;
                lto[i] = min(sum , le[i] - ri[i-1] -1);
                sum -= le[i] - ri[i-1] - 1;
                if(sum < 0) sum = 0;
            }

            ///計算每個點的前綴和。lowsum保存前綴和比當前點小的個數
            ll  ans = 0, lowsum = 0;
            int s = 0, pos = 0;
            f[g(0)] = 1;
            for(int i=1; i<=n; i++) {

                for(int j=max(pos, le[i] - lto[i]); j<=ri[i] + rto[i]; j++) {

                    if(j>=le[i] && j <= ri[i]) {
                        lowsum += f[g(s)];
                        s++;
                        f[g(s)]++;
                        ans += lowsum;
                    }
                    else {
                        s--;
                        lowsum -= f[g(s)];
                        f[g(s)]++;
                        ans += lowsum;
                    }
//                    cout<<j<<" "<<lowsum<<endl;
                    pos = j+1;
                }
            }
//            cout<<endl;
            printf("%lld\n", ans);
            return 0;
}
View Code

2019牛客暑期多校訓練營(第三場)

題號 標題 團隊的狀態
A Graph Games  通過
B Crazy Binary String  通過
C Guessing ETT 未通過
D Big Integer  通過
E Trees in the Pocket II 未通過
F Planting Trees  通過
G Removing Stones  通過
H Magic Line  通過
I Median  通過
J LRU management  通過

A

思路:將點按度數分成兩種點,大於$\sqrt{m}$的稱為大點,否則稱為小點。然后再對邊分塊,修改邊的話,邊緣塊直接修改,整塊直接反轉。

然后還需要先預處理出每個塊對大點的貢獻。對於每個小點暴力查詢連接的每條邊是否反轉;對於每個大點,考慮每個塊是否反轉,並對它產生多少貢獻。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
   
struct FastIO {
    static const int S = 4e6;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar() {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos++];
    }
    inline int xuint() {
        int c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x;
    }
    inline int xint()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    inline void xstring(char *s)
    {
        int c = xchar();
        while (c <= 32) c = xchar();
        for (; c > 32; c = xchar()) * s++ = c;
        *s = 0;
    }
    inline void wchar(int x)
    {
        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
        wbuf[wpos++] = x;
    }
    inline void wint(int x)
    {
        if (x < 0) wchar('-'), x = -x;
        char s[24];
        int n = 0;
        while (x || !n) s[n++] = '0' + x % 10, x /= 10;
        while (n--) wchar(s[n]);
        wchar('\n');
    }
    inline void wstring(const char *s)
    {
        while (*s) wchar(*s++);
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
} io;
const int N = 1e5 + 5;
vector<int> g[N];
int T, n, m, d[N], u[N*2], v[N*2], op, l, r, q, id[N*2];
LL val[N], res[N], f[N][500];
bool ty[N];
struct BLOCK {
    int bl[N*2], block, blo[1000];
    inline void init() {
        for (int i = 1; i <= m; ++i) bl[i] = (i-1)/block + 1;
        for (int i = 1; i <= bl[m]; ++i) blo[i] = 0;
    }
    inline void update(int L, int R) {
        if(bl[L] == bl[R]) {
            for (int i = L; i <= R; ++i) res[u[i]] ^= val[v[i]], res[v[i]] ^= val[u[i]];
            return ;
        }
        for (int i = L; i <= bl[L]*block; ++i) res[u[i]] ^= val[v[i]], res[v[i]] ^= val[u[i]];
        for (int i = bl[L]+1; i <= bl[R]-1; ++i) blo[i] ^= 1;
        for (int i = (bl[R]-1)*block+1; i <= R; ++i) res[u[i]] ^= val[v[i]], res[v[i]] ^= val[u[i]];
     }
}b;
int main() {
    mt19937 mt_rand(time(NULL));
    T = io.xint();
    while(T--) {
        n = io.xint(); m = io.xint();
        for (int i = 1; i <= n; ++i) val[i] = mt_rand()%LONG_MAX;
        for (int i = 1; i <= m; ++i) u[i] = io.xint(), v[i] = io.xint(), g[u[i]].pb(i), g[v[i]].pb(i), d[u[i]]++, d[v[i]]++;
        int blo = sqrt(m)+1;
        b.block = blo;
        b.init();
        for (int i = 1; i <= n; ++i) {
            if(d[i] <= blo) ty[i] = 0;
            else ty[i] = 1;
        }
        for (int i = 1; i <= n; ++i) if(ty[i]) for (int j = 1; j <= b.bl[m]; ++j) f[i][j] = 0;
        for (int i = 1; i <= n; ++i) {
            for (int id : g[i]) {
                int y = u[id]^v[id]^i;
                res[i] ^= val[y];
                if(ty[i]) f[i][b.bl[id]] ^= val[y];
            }
        }
        q = io.xint();
        for (int i = 1; i <= q; ++i) {
            op = io.xint();
            l = io.xint();
            r = io.xint();
            if(op == 1) {
                b.update(l, r);
            }
            else {
                LL v1 = res[l], v2 = res[r];
                if(ty[l]) {for (int j = 1; j <= b.bl[m]; ++j) if(b.blo[j]) v1 ^= f[l][j];}
                else for (int id : g[l]) if(b.blo[b.bl[id]]) v1 ^= val[u[id]^v[id]^l];
                if(ty[r]) {for (int j = 1; j <= b.bl[m]; ++j) if(b.blo[j]) v2 ^= f[r][j];}
                else for (int id : g[r]) if(b.blo[b.bl[id]]) v2 ^= val[u[id]^v[id]^r];
                putchar((v1==v2)+'0');
            }
        }
        putchar('\n');
        for(int i = 1; i <= n; ++i) d[i] = 0, g[i].clear(), res[i] = 0;
        for (int i = 1; i <= m; ++i) id[i] = 0;
    }
    return 0;
}
View Code

B

思路:對於最長子段的計算,只要把0看成-1,對於每個前綴和記錄最前面出現的位置

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e5 + 10;
char s[N];
int n, sum[N], a, b, c1, c0;
map<int, int> mp;
int main() {
    scanf("%d", &n);
    scanf("%s", s+1);
    for (int i = 1; i <= n; ++i) if(s[i] == '1') c1++; else c0++;
    b = min(c1, c0)*2;
    mp[0] = 0;
    for (int i = 1; i <= n; ++i) {
        if(s[i] == '1') sum[i] = sum[i-1]+1;
        else sum[i] = sum[i-1]-1;
        if(mp.find(sum[i]) != mp.end()) a = max(a, i-mp[sum[i]]);
        else mp[sum[i]] = i;
    }
    printf("%d %d\n", a, b);
    return 0;
}
View Code

C

D

思路:首先有一個公式$\frac{x}{d}\%k = \frac{x\%k*d}{d}$。那么原式$\frac{10^x-1}{9}\%p$可以化簡$10^x = 1(\%(9*p))$。或者模數不乘$9$,但$p=3$時要特判。

當$p = 2, 5$時,答案肯定是$0$。否則,求出最小的x滿足等式,這個可以用費馬小定理或者BSGS。然后就是求多少對$(i, j)$使得$x | i^j$。我們先把$x$分解

質因數$x={p_1}^{a_1} {p_2}^{a_2}...{p_n}^{a_n}$,然后枚舉$j$,那么對於一個固定的$j$,我們發現$y = p_{1}^{\lceil\frac{a_{1}}{j}\rceil}p_{2}^{\lceil\frac{a_{2}}{j}\rceil}...p_{n}^{\lceil\frac{a_{n}}{j}\rceil} $的倍數的$j$次方一定是$x$的倍數, 那么就是求小於$n$的數中有多少個是$y$的倍數。當$j \ge 30$時,$y$的質因子的冪次都變成了$1$。

代碼:

#include<bits/stdc++.h>
#define ll long long
#define LL long long
using namespace std;
LL qpow(LL n, LL k) {
    LL ans = 1;
    if(k == -1) return 0;
    while(k) {
        if(k&1) ans = (ans*n);
        n = (n*n);
        k >>= 1;
    }
    return ans;
}
unordered_map<int, int> mp;
LL q_pow(LL n, LL k, LL p) {
    LL ans = 1;
    if(k == -1) return 0;
    while(k) {
        if(k&1) ans = (ans*n) % p;
        n = (n*n) % p;
        k >>= 1;
    }
    return ans;
}
int BSGS(int a, int b, int p){
    int m = sqrt(p)+1, s = b;
    mp.clear();
    for(int i = 0; i < m; ++i){
        mp[s]=i;
        s= (s*1LL*a)%p;
    }
    int t = q_pow(a, m, p);
    s = 1;
    for(int i = 1; i <= m; ++i){
        s = (s*1LL*t)%p;
        if(mp.find(s) != mp.end()) return i*m-mp[s];
    }
    return -1;
}
int p,n,m;
vector<pair<int,int> > vs;
void make(int p){
    vs.clear();
    for(int i=2;i*i<=p;i++){
        if(p%i==0){
            int c=0;
            while(p%i==0){
                c++; p/=i;
            }
            vs.push_back({i,c});
        }
    }
    if(p!=1) vs.push_back({p,1});
    ll num=0;
    ll temp=1;
    for(int j=1;j<=min(30,m);j++){
        temp=1;
        for(int i=0; i<vs.size(); i++){
            temp=temp*qpow(vs[i].first,ceil(1.0*vs[i].second/j));
        }
        num+=n/temp;
    }
    if (m>30) num+=1ll*(m-30)*(n/temp);
    printf("%lld\n",num);
}
int main(){
    int T; scanf("%d",&T);
    while(T--){
        scanf("%d %d %d",&p,&n,&m);
        if(p==2 || p==5) { printf("0\n"); continue; }
        int x=BSGS(10,1,p);// cout<<x<<endl;
        if(p==3) x=3;
        make(x);
    }
}
View Code

E

F

思路:用枚舉上邊界l和下邊界r,先對於每一列求出最大值最小值,然后用單調隊列維護。這道題很卡常,有個用兩次單調隊列的$n^3$寫法被卡掉了。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
   
const int N = 505;
const int INF = 0x3f3f3f3f;
int a[N][N], mn[N], mx[N];
int q1[N*2], q2[N*2], T, n, m;
int main() {
    scanf("%d", &T);
    while(T--){
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) scanf("%d", &a[i][j]);
        int ans = 0;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) mn[j] = INF, mx[j] = -INF;
            for (int j = i; j <= n; ++j) {
                for (int k = 1; k <= n; ++k) mn[k] = min(a[j][k], mn[k]), mx[k] = max(a[j][k], mx[k]);
                int le1 = N, ri1 = N-1;
                int le2 = N, ri2 = N-1;
                int pre = 0;
                for (int k = 1; k <= n; ++k) {
                    while(le1 <= ri1 && mn[q1[ri1]] >= mn[k]) ri1--;
                    q1[++ri1] = k;
                    while(le2 <= ri2 && mx[q2[ri2]] <= mx[k]) ri2--;
                    q2[++ri2] = k;
                    while(pre < k && mx[q2[le2]]-mn[q1[le1]] > m) {
                        ++pre;
                        while(le1 <= ri1 && q1[le1] <= pre) le1++;
                        while(le2 <= ri2 && q2[le2] <= pre) le2++;
                    }
                    if(pre < k && mx[q2[le2]] - mn[q1[le1]] <=m) ans = max(ans, (k - pre)*(j-i+1));
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

G

思路:分治,對於每個分治的區間$[L,R]$,求出最大值的位置$p$,然后枚舉$[L,p]$或者$[p,R]$中小的區間中的每個位置,然后找另一個端點的位置。

然后遞歸區間$[L,p-1]$和區間$[p+1,R]$。時間復雜度$O(n*log(n))$

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 3e5 + 5;
int T, n, a[N], st[N][20], lg[N];
LL sum[N];
LL ans = 0;
inline void init() {
    for (int i = n; i >= 1; --i) {
        st[i][0] = i;
        for (int j = 1; i+(1<<j-1)-1 <= n; ++j) {
            if(a[st[i][j-1]] > a[st[i+(1<<j-1)][j-1]]) st[i][j] = st[i][j-1];
            else st[i][j] = st[i+(1<<j-1)][j-1];
        }
    }

}
inline int get_max(int L, int R) {
    int k = lg[R-L+1], x = st[L][k], y = st[R-(1<<k)+1][k];
    if(a[x] > a[y]) return x;
    else return y;
}
void solve(int L, int R) {
    if(L >= R) return ;
    int p = get_max(L, R);
    if(p-L < R-p) {
        int j = p;
        for (int i = L; i <= p; ++i) {
            while(j <= R && sum[j]-sum[i-1] < 2*a[p]) ++j;
            ans += R-j+1;
        }
    }
    else {
        int j = p;
        for (int i = R; i >= p; --i) {
            while(j >= L && sum[i]-sum[j==0?j:j-1] < 2*a[p]) --j;
            ans += j-L+1;
        }
    }
    solve(L, p-1);
    solve(p+1, R);
}
int main() {
    for (int i = 2; i < N; ++i) lg[i]=lg[i>>1]+1;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), sum[i] = sum[i-1]+a[i]; init();
        ans = 0;
        solve(1, n);
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

H

思路:構造

代碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e3+10;
vector<int> vs[maxn];
int32_t main(){
    int T; scanf("%d",&T);
    while(T--){
        int n; scanf("%d",&n);
        for(int i=1;i<=n;i++){
           int x,y; scanf("%d %d",&x,&y); x+=1000; y+=1000;
           vs[x].push_back(y);
        }
        int temp=0;
        for(int i=0;i<=2000;i++){
            if(temp+vs[i].size()>=n/2){
                int d=n/2-temp;   sort(vs[i].begin(),vs[i].end());
                int y=vs[i][d-1];
                if(y>=1000){
                    int x1=i+1;     x1-=1000;
                    int y1=-1;      y1-=1000;
                    int x2=i+3;     x2-=1000;
                    int y2=-2*y-4;  y2-=1000;
                    printf("%d %d %d %d\n",x1,y1,x2,y2);
                }
                else {
                    int x1=i-1;
                    int y1=2001;
                    int x2=i-3;
                    int y2=-2*y+6003-1;
                    printf("%d %d %d %d\n",x1-1000,y1-1000,x2-1000,y2-1000);
 
                }
                break;
            }
            temp+=vs[i].size();
        }
        for(int i=0;i<=2000;i++) vs[i].clear();
    }
}
View Code

I

思路:如果可以構造,那么$a_i$一定可以選擇$b_i,b_{i-1},b_{i-2}$中的一個值,具體證明看題解。那么可以想到一個狀態$dp[i][j][k]$,其中,$j$和$k$

分別表示$i$和$i-1$這兩個位置選擇的$b_i$和本身之間的距離,那判斷一下相鄰兩個之間的轉移可不可行就可以轉移了。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
bool dp[N][3][3];
int pre[N][3][3];
int T, n, b[N], a[N];
inline int ck(int x, int y, int z) {
    if(b[x] >= b[y] && b[x] >= b[z]) return max(b[y], b[z]);
    if(b[y] >= b[x] && b[y] >= b[z]) return max(b[x], b[z]);
    return max(b[x], b[y]);
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n-2; ++i) scanf("%d", &b[i]);
        if(n == 3) {
            for (int i = 1; i <= 3; ++i) printf("%d ", b[1]);
            printf("\n");
            continue;
        }
        for (int i = 1; i <= n; ++i) for (int j = 0; j < 3; ++j) for (int k = 0; k < 3; ++k) dp[i][j][k] = 0;
        for (int i = 1; i <= n; ++i) {
            if(i == 1) ;
            else if(i == 2) {
                for (int j = 0; j < 3; ++j) {
                    if(2-j < 1) break;
                    for (int k = 0; k < 3; ++k) {
                        if(1-k < 1) break;
                        dp[i][j][k] = 1;
                    }
                }
            }
            else {
                for (int j = 0; j < 3; ++j) {
                    for (int k = 0; k < 3; ++k) {
                        if(dp[i-1][j][k]) {
                            for (int l = 0; l < 3; ++l) {
                                if(i-l <= n-2) {
                                    if(ck(i-2-k, i-1-j, i-l) == b[i-2]) dp[i][l][j] = 1, pre[i][l][j] = k;
                                }
                            }
                        }
                    }
                }
            }
        }
        int x, y, z;
        bool f = false;
        for (int j = 0; j < 3; ++j) for (int k = 0; k < 3; ++k) if(dp[n][j][k]) {
            f = true;
            x = n; 
            y = j;
            z = k;
            break;
        }
        if(f) {
            while(x) {
                a[x] = b[x-y];
                int tmp = z;
                z = pre[x][y][z];
                y = tmp;
                x--;
            }    
            for (int i = 1; i <= n; ++i) printf("%d%c", a[i], " \n"[i==n]); 
        }
        else printf("-1\n");
    }
    return 0;
}
View Code

J

思路:用平衡樹維護,其實用set就可以了,記錄一下每個串最后的位置,如果這個串被刪除,也要記得刪除位置

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 5e5 + 10;
int ch[N][2], val[N], cnt[N], V[N], fa[N], sz[N], ncnt = 0, rt = 0;
string tmp[N];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
void Find(int x) {
    if(!rt) return ;
    int cur = rt;
    while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
    Splay(cur);
}
void Insert(int x, int y, string s) {
    int cur = rt, p = 0;
    while(cur && val[cur] != x) {
        p = cur;
        cur = ch[cur][x>val[cur]];
    }
    if(cur) cnt[cur]++;
    else {
        cur = ++ncnt;
        if(p) ch[p][x>val[p]] = cur;
        fa[cur] = p;
        ch[cur][0] = ch[cur][1] = 0;
        val[cur] = x;
        V[cur] = y;
        tmp[cur] = s;
        cnt[cur] = sz[cur] = 1;
    }
    Splay(cur);
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
inline int get_min(int x) {
    while(x && ch[x][0]) x = ch[x][0];
    return x;
}
inline int get_max(int x) {
    while(x && ch[x][1]) x = ch[x][1];
    return x;
}
int Pre(int x) {
    Find(x);
    if(val[rt] < x) return rt;
    if(!ch[rt][0]) return -1;
    int cur = ch[rt][0];
    while(ch[cur][1]) cur = ch[cur][1];
    return cur;
}
int Succ(int x) {
    Find(x);
    if(val[rt] > x) return rt;
    if(!ch[rt][1]) return -1;
    int cur = ch[rt][1];
    while(ch[cur][0]) cur = ch[cur][0];
    return cur;
}
void Remove(int x) {
    int last = Pre(x), next = Succ(x);
    Splay(last), Splay(next, last);
    int del = ch[next][0];
    if(cnt[del] > 1) cnt[del]--, Splay(del);
    else ch[next][0] = 0, push_up(next), push_up(last);
}
void delete_root() {
    if(ch[rt][1]) {
        int cur = ch[rt][1];
        while(cur && ch[cur][0]) cur = ch[cur][0];
        Splay(cur, rt);
        ch[cur][0] = ch[rt][0];
        fa[ch[cur][0]] = cur;
        rt = cur;
    }
    else rt = ch[rt][0];
    fa[rt] = 0;
    if(rt) push_up(rt);
}
inline void init() {
    ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = val[0] = 0;
   // V[0] = -10;
}
int q, m, op, v, T;
string s;
unordered_map<string, int> mp;
int main() {
    fio;
    cin >> T;
    while(T--) {
        init();
        mp.clear();
        Insert(-1, -10, "0");
        Insert(N-1, -10, "0");
        cin >> q >> m;
        int now = 0;
        for (int i = 1; i <= q; ++i){
            cin >> op >> s >> v;
            int res = 0;
            if(op == 0) {
                 
                if(mp.find(s) == mp.end()) {
                    mp[s] = ++now;
                    Insert(now, v, s);
                    res = v;
                }
                else {
                    Find(mp[s]);
                    res = V[rt];
                    Remove(mp[s]);
                    mp[s] = ++now;
                    Insert(now, res, s);
                }
                cout << res << "\n";
            }
            else {
                if(mp.find(s) == mp.end()) {
                    cout << "Invalid\n";
                }
                else {
                    if(v == 0) {
                        Find(mp[s]);
                        cout <<  V[rt] << "\n";
                    }
                    else if(v == -1) {
                        int cur = Pre(mp[s]);
                        if(V[cur] == -10) cout << "Invalid\n";
                        else cout <<  V[cur] << "\n";
                    }
                    else {
                        int cur = Succ(mp[s]);
                        if(V[cur] == -10) cout << "Invalid\n";
                        else cout <<  V[cur] << "\n";
                    }
                }
            }
            if(sz[rt]-2 > m) {
                int cur = Kth(2);
                Splay(cur);
                delete_root();
                mp.erase(tmp[cur]);
            }
        }
    }
    return 0;
}
View Code

2019牛客暑期多校訓練營(第四場)

題號 標題 團隊的狀態
A meeting  通過
B xor  通過
C sequence  通過
D triples I  通過
E triples II  通過
F merge  通過
G tree 未通過
H RNGs 未通過
I string  通過
J free  通過
K number  通過

A

思路:虛樹直徑的一半。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
vector<int> g[N];
int a[N], sz[N], sum[N], n, k, u, v, s, mx;
void dfs(int u, int o, int d) {
    if(a[u]) {
        if(d > mx) {
            mx = d;
            s = u;
        }
    }
    for (int v : g[u]) {
        if(v != o){
            dfs(v, u, d+1);
        }
    }
}
int main() {
    scanf("%d %d", &n, &k);
    for (int i = 1; i < n; ++i) {
        scanf("%d %d", &u, &v);
        g[u].pb(v);
        g[v].pb(u);
    }
    for (int i = 1; i <= k; ++i) scanf("%d", &u), ++a[u];
    dfs(u, u, 0);
    dfs(s, s, 0);
    if(mx%2) printf("%d\n", (mx+1)/2);
    else printf("%d\n", mx/2);
    return 0;
}
View Code

B

思路:線性基求交+線段樹。建樹的復雜度是$O(n*32*32)$,查詢時不需要把需要查詢區間的交算出來,不然單次查詢復雜度$O(32*32*log(n))$,

只需要判斷這段區間在線段樹上的每個節點是不是可以表示$x$就可以了,這樣單次查詢復雜度$O(32*log(n))$。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
  
const int N = 5e4 + 5;
struct LinearBase {
    LL v[32];
    inline void clr() {memset(v, 0, sizeof(v));}
    inline void ins(LL a) {
        for (int i = 31; i >= 0; --i) {
            if(a&(1LL<<i)) {
                if(!v[i]) {
                    v[i] = a;
                    break;
                }
                a ^= v[i];
            }
        }
    }
    inline bool can_ex(LL a) {
        for (int i = 31; i >= 0; --i) if((a^v[i]) < a)  a ^= v[i];
        return a == 0;
    }
    //
    inline friend LinearBase operator * (const LinearBase &a, const LinearBase &b) {
        LinearBase all, c, d;
        all.clr(), c.clr(), d.clr();
        for (int i = 31; i >= 0; --i) {
            all.v[i] = a.v[i];
            d.v[i] = 1LL<<i;
        }
        for (int i = 31; i >= 0; --i) {
            if(b.v[i]) {
                LL v = b.v[i], k = 0;
                bool can = true;
                for (int j = 31; j >= 0; --j) {
                    if(v&(1LL<<j)) {
                        if(all.v[j]) {
                            v ^= all.v[j];
                            k ^= d.v[j];
                        }
                        else {
                            can = false;
                            all.v[j] = v;
                            d.v[j] = k;
                            break;
                        }
                    }
                }
                if(can) {
                    LL v = 0;
                    for (int j = 31; j >= 0; --j) {
                        if(k&(1LL<<j)) {
                            v ^= a.v[j];
                        }
                    }
                    c.ins(v);
                }
            }
        }
        return c;
    }
}tree[N<<2];
vector<LL> vc[N];
inline void push_up(int rt) {
    tree[rt] = tree[rt<<1]*tree[rt<<1|1];
}
void build(int rt, int l, int r) {
    if(l == r) {
        tree[rt].clr();
        for (LL x : vc[l]) tree[rt].ins(x);
        return ;
    }
    int m = l+r >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
bool query(int L, int R, LL a, int rt, int l, int r) {
    if(L <= l && r <= R) return tree[rt].can_ex(a);
    int m = l+r >> 1;
    if(L <= m && m < R) return query(L, R, a, ls)&query(L, R, a, rs);
    if(L <= m) return query(L, R, a, ls);
    else return query(L, R, a, rs);
}
int n, m, t, l, r;
LL a;
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &t);
        vc[i].resize(t);
        for (int j = 0; j < t; ++j) scanf("%lld", &vc[i][j]);
    }
    build(1, 1, n);
    while(m--) {
        scanf("%d %d %lld", &l, &r, &a);
        if(query(l, r, a, 1, 1, n)) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
View Code

C

思路:南昌邀請賽原題。

先對b數組求個前綴和,然后用單調棧求出以每個位置$p$為最小值左端點的最左邊$L$和右端點的最右邊$R$。

如果$a[p] > 0$,用$max\left(sum[i], i\in[p, R]\right)- min\left(sum[i], i\in[L-1, p-1]\right)$;

如果$a[p] < 0$,用$min\left(sum[i], i\in[p, R]\right)- max\left(sum[i], i\in[L-1, p-1]\right)$。

方法一(單調棧+線段樹$O(nlog(n))2500ms$)

代碼:

#include <bits/stdc++.h>
 
using namespace std;
#define LL long long
#define fi first
#define se second
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
const int N = 3e6 + 5;
int a[N], b[N], pre[N], suf[N];
LL sum[N], mx[N<<2], mn[N<<2];
stack<int> st;
int n;
void push_up(int rt) {
    mn[rt] = min(mn[rt<<1], mn[rt<<1|1]);
    mx[rt] = max(mx[rt<<1], mx[rt<<1|1]);
}
void build(int rt, int l, int r) {
    if(l == r) {
        mx[rt] = mn[rt] = sum[l];
        return ;
    }
    int m = l+r >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
LL querymx(int L, int R, int rt, int l, int r) {
    if(L <= l && r <= R) return mx[rt];
    int m = l+r >> 1;
    LL ans = LONG_MIN;
    if(L <= m) ans = max(ans, querymx(L, R, ls));
    if(R > m) ans = max(ans, querymx(L, R, rs));
    return ans;
}
LL querymn(int L, int R, int rt, int l, int r) {
    if(L <= l && r <= R) return mn[rt];
    int m = l+r >> 1;
    LL ans = LONG_MAX;
    if(L <= m) ans = min(ans, querymn(L, R, ls));
    if(R > m) ans = min(ans, querymn(L, R, rs));
    return ans;
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
    for (int i = 1; i <= n; ++i) sum[i] = sum[i-1] + b[i];
    build(1, 0, n);
    a[0] = a[n+1] = INT_MIN;
    st.push(0);
    for (int i = 1; i <= n; ++i) {
        while(!st.empty() && a[st.top()] >= a[i]) st.pop();
        pre[i] = st.top();
        st.push(i);
    }
    while(!st.empty()) st.pop();
    st.push(n+1);
    for (int i = n; i >= 1; --i) {
        while(!st.empty() && a[st.top()] >= a[i]) st.pop();
        suf[i] = st.top();
        st.push(i);
    }
    LL ans = -(1LL<<61);
    for (int i = 1; i <= n; ++i) {
        int l = pre[i], r = i-1;
        int ll = i, rr = suf[i]-1;
        if(a[i] < 0) {
            ans = max(ans, a[i]*(querymn(ll, rr, 1, 0, n)-querymx(l, r, 1, 0, n)));
        }
        else if(a[i] > 0) {
            ans = max(ans, a[i]*(querymx(ll, rr, 1, 0, n)-querymn(l, r, 1, 0, n)));
        }
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

方法二(笛卡爾樹+快讀$O(n)350ms$,這個快讀優化了1200ms,出題人為了卡$log$連讀入都卡掉了)

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

struct FastIO {
    static const int S = 4e6;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar() {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos++];
    }
    inline int xuint() {
        int c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x;
    }
    inline int xint()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    inline void xstring(char *s)
    {
        int c = xchar();
        while (c <= 32) c = xchar();
        for (; c > 32; c = xchar()) * s++ = c;
        *s = 0;
    }
    inline void wchar(int x)
    {
        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
        wbuf[wpos++] = x;
    }
    inline void wint(int x)
    {
        if (x < 0) wchar('-'), x = -x;
        char s[24];
        int n = 0;
        while (x || !n) s[n++] = '0' + x % 10, x /= 10;
        while (n--) wchar(s[n]);
        wchar('\n');
    }
    inline void wstring(const char *s)
    {
        while (*s) wchar(*s++);
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
} io;

const int N = 3e6 + 10;
struct Node {
    int id, key, par, ch[2];
    LL mxlf, mxri, mnlf, mnri;
    inline bool operator < (Node & rhs) {return id < rhs.id;}
    inline void init(int _id, int _key, int _par) {
        key = _key, id = _id, par = _par, ch[0] = ch[1] = 0;
    }
}tree[N];
inline int cartesian_build(int n) {
    for (int i = 1; i <= n; ++i) {
        int k = i-1;
        while(tree[k].key > tree[i].key) k = tree[k].par;
        tree[i].ch[0] = tree[k].ch[1];
        tree[tree[i].ch[0]].par = i;
        tree[k].ch[1] = i;
        tree[i].par = k;
    }
    return tree[0].ch[1];
}
LL ans = LONG_MIN, sum[N];
int n, a[N], b[N], rt;
inline void dfs(int u) {
    tree[u].mxlf = tree[u].mnlf =  sum[u-1];
    tree[u].mxri = tree[u].mnri = sum[u];
    if(tree[u].ch[0]) dfs(tree[u].ch[0]), tree[u].mxlf = max(tree[u].mxlf, tree[tree[u].ch[0]].mxlf), tree[u].mnlf = min(tree[u].mnlf, tree[tree[u].ch[0]].mnlf);
    if(tree[u].ch[1]) dfs(tree[u].ch[1]), tree[u].mxri = max(tree[u].mxri, tree[tree[u].ch[1]].mxri), tree[u].mnri = min(tree[u].mnri, tree[tree[u].ch[1]].mnri);
    if(tree[u].key > 0) ans = max(ans, tree[u].key*(tree[u].mxri-tree[u].mnlf));
    else ans = max(ans, tree[u].key*(tree[u].mnri-tree[u].mxlf));
    if(tree[u].ch[0]) tree[u].mxri = max(tree[u].mxri, tree[tree[u].ch[0]].mxri), tree[u].mnri = min(tree[u].mnri, tree[tree[u].ch[0]].mnri);
    if(tree[u].ch[1]) tree[u].mxlf = max(tree[u].mxlf, tree[tree[u].ch[1]].mxlf), tree[u].mnlf = min(tree[u].mnlf, tree[tree[u].ch[1]].mnlf);
}
int main() {
    n = io.xint();
    for (int i = 1; i <= n; ++i) a[i] = io.xint();
    tree[0].init(0, -1000001, 0);
    for (int i = 1; i <= n; ++i) b[i] = io.xint(), sum[i] = sum[i-1]+b[i], tree[i].init(i, a[i], 0);
    rt = cartesian_build(n);
    dfs(rt);
    printf("%lld\n", ans);
    return 0;
}
View Code

D

思路:$2^p\%3$:如果$p$是偶數,是1;如果$p$奇數,是2。

然后如果$a\%3==0$,答案就是本身;如果$a\% 3==1$,可以取出一個偶數位或兩個奇數位,然后考慮怎把這些位和之前的位構成3的倍數;如果$a\%3==2$,同理。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int T;
LL a;
vector<int> vc[2];
vector<LL> res;
int main() {
    scanf("%d", &T);
    while(T--) {
        vc[0].clear();
        vc[1].clear();
        res.clear();
        scanf("%lld", &a);
        for (int i = 0; i <= 61; ++i) {
            if(a&(1LL<<i)) vc[i%2].pb(i);
        }
        if(a%3 == 0) {
            res.pb(a);
        }
        else if(a%3 == 2) {
            bool f = false;
            if(vc[1].size() > 0) {
                if(vc[0].size() > 0) {
                    int x = vc[1][0], y = vc[0][0];
                    res.pb(a^(1LL<<x));
                    res.pb((1LL<<x)|(1LL<<y));
                    f = true;
                }
                if(vc[1].size() >= 3) {
                    int x = vc[1][0], y = vc[1][1], z = vc[1][2];
                    res.pb(a^(1LL<<x));
                    res.pb((1LL<<x)^(1LL<<y)^(1LL<<z));
                    f = true;
                }
            }
            if(!f && vc[0].size() >= 3) {
                int x = vc[0][0], y = vc[0][1], z = vc[0][2];
                res.pb(a^(1LL<<x)^(1LL<<y));
                res.pb((1LL<<x)^(1LL<<y)^(1LL<<z));
                f = true;
            }
 
        }
        else {
            bool f = false;
            if(vc[0].size() > 0) {
                if(vc[1].size() > 0) {
                    int x = vc[0][0], y = vc[1][0];
                    res.pb(a^(1LL<<x));
                    res.pb((1LL<<x)|(1LL<<y));
                    f = true;
                }
                if(vc[0].size() >= 3) {
                    int x = vc[0][0], y = vc[0][1], z = vc[0][2];
                    res.pb(a^(1LL<<x));
                    res.pb((1LL<<x)^(1LL<<y)^(1LL<<z));
                    f = true;
                }
            }
            if(!f && vc[1].size() >= 3) {
                int x = vc[1][0], y = vc[1][1], z = vc[1][2];
                res.pb(a^(1LL<<x)^(1LL<<y));
                res.pb((1LL<<x)^(1LL<<y)^(1LL<<z));
                f = true;
            }
        }
        printf("%d ", (int)res.size());
        //LL t = 0;
        for (int i = 0; i <res.size(); ++i) printf("%lld%c", res[i], " \n"[i+1==res.size()]);
        //cout << t << endl;
    }
    return 0;
}
View Code

E

思路:二維二項式反演。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
  
const int MOD = 998244353;
int T, c1, c2;
LL n, a, C[65][65], f[65][65];
inline LL q_pow(LL n, LL k) {
    LL res = 1;
    while(k) {
        if(k&1) res = (res*n)%MOD;
        n = (n*n)%MOD;
        k >>= 1;
    }
    return res;
}
inline void init() {
    C[0][0] = 1;
    for (int i = 1; i < 65; ++i) {
        C[i][0] = 1;
        for (int j = 1; j <= i; ++j) C[i][j] = (C[i-1][j]+C[i-1][j-1])%MOD;
    }
    for (int i = 0; i < 65; ++i) {
        for (int j = 0; j < 65; ++j) {
            for (int ii = 0; ii <= i; ++ii) {
                for (int jj = 0; jj <= j; ++jj) {
                    if((ii*1+jj*2)%3 == 0) {
                        (f[i][j] += C[i][ii]*C[j][jj]%MOD) %= MOD;
                    }
                }
            }
        }
    }
}
int main() {
    init();
    scanf("%d", &T);
    while(T--) {
        scanf("%lld %lld", &n, &a);
        c1 = c2 = 0;
        for (int i = 0; i <= 60; ++i) {
            if(a&(1LL<<i)) {
                if(i%2 == 0) ++c1;
                else ++c2;
            }
        }
        LL ans = 0;
        for (int i = 0; i <= c1; ++i) {
            for (int j = 0; j <= c2; ++j) {
                if((c1-i+c2-j)%2 == 0) (ans += C[c1][i]*C[c2][j]%MOD*q_pow(f[i][j], n)) %= MOD;
                else (ans -= C[c1][i]*C[c2][j]%MOD*q_pow(f[i][j], n)) %= MOD;
            }
        }
        ans = (ans + MOD) % MOD;
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

F

思路:fhq treap。split操作換成按位置split。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head


struct fhq_treap {
    static const int N = 1e5 + 5;
    struct Node {
        int val, mx, key, lc, rc, sz;
    }tree[N];
    int rt, tot;
    inline void init() {
        rt = tot = 0;
        tree[rt].sz = tree[rt].val = tree[rt].mx = tree[rt].lc = tree[rt].rc = 0;
        srand(time(0));
    }
    inline void update(int rt) {
        tree[rt].mx = max(tree[rt].val, max(tree[tree[rt].lc].mx, tree[tree[rt].rc].mx));
        tree[rt].sz = tree[tree[rt].lc].sz + tree[tree[rt].rc].sz + 1;
    }
    void split(int rt, int &a, int &b, int x) {
        if(rt == 0) {a = b = 0; return ;}
        if(tree[tree[rt].lc].sz+1 <= x) {
            a = rt;
            split(tree[rt].rc, tree[a].rc, b, x-tree[tree[rt].lc].sz-1);
        }
        else {
            b = rt;
            split(tree[rt].lc, a, tree[b].lc, x);
        }
        update(rt);
    }
    void merge(int &rt, int a, int b) {
        if(a==0 || b==0) {
            rt = a+b;
            return ;
        }
        if(tree[a].key < tree[b].key) {
            rt = a;
            merge(tree[rt].rc, tree[a].rc, b);
        }
        else {
            rt = b;
            merge(tree[rt].lc, a, tree[b].lc);
        }
        update(rt);
    }
    inline int new_node() {
        tree[++tot].sz = 1;
        scanf("%d", &tree[tot].val);
        tree[tot].mx = tree[tot].val;
        tree[tot].lc = tree[tot].rc = 0;
        tree[tot].key = rand()*rand();
        return tot;
    }
    void ins(int &rt) {
        int node = new_node();
        merge(rt, rt, node);
    }
    void delete_node(int &rt, int val) {
        int x = 0, y = 0, z = 0;
        split(rt, x, y, val);
        split(x, x, z, val-1);
        merge(z, tree[z].lc, tree[z].rc);
        merge(x, x, z);
        merge(rt, x, y);
    }
    inline int get_kth(int rt, int k) {
        while(tree[tree[rt].lc].sz+1 != k) {
            if(tree[tree[rt].lc].sz >= k) rt = tree[rt].lc;
            else k -= tree[tree[rt].lc].sz+1, rt = tree[rt].rc;
        }
        return tree[rt].val;
    }
    int get_pos(int rt, int x) {
        if(!rt) return 0;
        if(tree[tree[rt].lc].mx > x) return get_pos(tree[rt].lc, x);
        else if(tree[rt].val > x) return tree[tree[rt].lc].sz;
        else return get_pos(tree[rt].rc, x)+tree[tree[rt].lc].sz+1;
    }
    int get_rnk(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x, y, val-1);
        int tmp = tree[x].sz+1;
        merge(rt, x, y);
        return tmp;
    }
    int get_pre(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x,  y, val-1);
        int tmp = get_kth(x, tree[x].sz);
        merge(rt, x, y);
        return tmp;
    }
    int get_scc(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x, y, val);
        int tmp = get_kth(y, 1);
        merge(rt, x, y);
        return tmp;
    }
}t;
void solve(int l, int m, int r) {
    int x = 0, y = 0;
    t.split(t.rt, x, y, r);
    t.rt = x;
    int a = 0, b = 0;
    t.split(t.rt, a, b, m);
    t.rt = 0;
    while(a&&b) {
        int va = t.get_kth(a, 1), vb = t.get_kth(b, 1);
        if(va > vb) swap(va, vb), swap(a, b);
        int p = t.get_pos(a, vb), tmp;
        t.split(a, tmp, a, p);
        t.merge(t.rt, t.rt, tmp);
    }
    if(a) t.merge(t.rt, t.rt, a);
    if(b) t.merge(t.rt, t.rt, b);
    t.merge(t.rt, t.rt, y);
}
int n, m, op, l, p, r;
int main() {
    t.init();
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) t.ins(t.rt);
    for (int i = 1; i <= m; ++i) {
        scanf("%d", &op);
        if(op == 1) {
            scanf("%d %d %d", &l, &p, &r);
            solve(l, p, r);
        }
        else {
            scanf("%d", &p);
            printf("%d\n", t.get_kth(t.rt, p));
        }
    }
    return 0;
}
View Code

G

H

I

思路:后綴數組+回文自動機。

先將原串反轉放在原來的串的后面,用后綴數組求出本質不同的串的個數$a$,然后用回文自動機求出本質不同的回文串的個數$b$,然后$\frac{a+b}{2}$就是答案。

隊友的板子真丑。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  
const int maxn=4e5+10;
char s[maxn];
int y[maxn],x[maxn],c[maxn],sa[maxn],rk[maxn],height[maxn];
int n,m,now,sz;
int get_sa()
{
    for (int i=0;i<=m;i++) c[i]=0;
    for (int i=1;i<=n;++i) ++c[x[i]=s[i]];
    for (int i=2;i<=m;++i) c[i]+=c[i-1];
    for (int i=n;i>=1;--i) sa[c[x[i]]--]=i;
    for (int k=1;k<=n;k<<=1)
    {
        int num=0;
        for (int i=n-k+1;i<=n;++i) y[++num]=i;
        for (int i=1;i<=n;++i) if (sa[i]>k) y[++num]=sa[i]-k;
        for (int i=1;i<=m;++i) c[i]=0;
        for (int i=1;i<=n;++i) ++c[x[i]];
        for (int i=2;i<=m;++i) c[i]+=c[i-1];
        for (int i=n;i>=1;--i) sa[c[x[y[i]]]--]=y[i],y[i]=0;
        swap(x,y);
        x[sa[1]]=1;num=1;
        for (int i=2;i<=n;++i)
        x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]) ? num : ++num;
        if (num==n) break;m=num;
    }
}
int get_height()
{
    int k=0;
    for (int i=1;i<=n;++i) rk[sa[i]]=i;
    for (int i=1;i<=n;++i)
    {
        if (rk[i]==1) continue;//第一名height為0
        if (k) --k;//h[i]>=h[i-1]+1;
        int j=sa[rk[i]-1];
        while (j+k<=n && i+k<=n && s[i+k]==s[j+k]) ++k;
        height[rk[i]]=k;//h[i]=height[rk[i]];
    }
}
const double eps = 1E-8;
const int dx4[4]={1,0,0,-1};
const int dy4[4]={0,-1,1,0};
const int inf = 0x3f3f3f3f;
const int N=2e5+7;
struct PAM
{
    int fail,cnt,len;
    int nxt[26];
}st[N];
char RS[N];
string S;
  
void pam_init()
{
    mem(st,0);
    st[0].fail = st[1].fail = 1;
    st[1].len = -1;
    sz = 1;
}
void extend(int c,int pos)
{
    int p = now;
    while (S[pos-st[p].len-1]!=S[pos]) p = st[p].fail;
    if (!st[p].nxt[c]){
    int np=++sz,q=st[p].fail;
    st[np].len=st[p].len+2;
    while (S[pos-st[q].len-1]!=S[pos]) q=st[q].fail;
    st[np].fail=st[q].nxt[c];
    st[p].nxt[c] = np;
    }
    now=st[p].nxt[c];
    st[now].cnt++;
}
int main()
{
    string ss;  cin>>ss;   int t=ss.size();
    S=ss;
    ss="#"+ss+"#";
    reverse(S.begin(), S.end());
    ss += S;
    n=ss.size(); n--;  for(int i=1;i<=n;i++) s[i]=ss[i];
    m=122;
    get_sa(); get_height();
    LL ans=n*1LL*(n+1)/2-1LL*(t+1)*(t+1); //cout<<ans<<endl;
    for(int i=1;i<=n;i++) ans-=height[i];
    for(int i=0;i<=n;i++)
    {
        x[i]=0; y[i]=0; sa[i]=0; rk[i]=0; height[i]=0;
    }
    n = S.size();
    pam_init();
    for ( int i = 0 ; i < n; i++) extend(S[i]-'a',i);
    ans -= sz-1;
    ans /= 2;
    ans += sz-1;
    printf("%lld\n",ans);
}
View Code

J

思路:分層圖最短路

代碼:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
 
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
/**********showtime************/
 
            const int maxn = 1e3+9;
            vector<pii> mp[maxn];
            int dis[maxn][maxn];
 
            int n,m,s, t, k;
            void bfs(int s) {
                memset(dis, inf, sizeof(dis));
                dis[s][0] = 0;
                queue<pii>que;
                que.push(pii(s, 0));
                while(!que.empty()){
                    int u = que.front().fi;
                    int tk = que.front().se;
                    que.pop();
                    for(pii p : mp[u]) {
                        int v = p.fi, w = p.se;
                        if(tk < k && dis[v][tk+1] > dis[u][tk]) {
                            dis[v][tk+1] = dis[u][tk];
                            que.push(pii(v, tk+1));
                        }
                        if(dis[v][tk] > dis[u][tk] + w) {
                            dis[v][tk] = dis[u][tk] + w;
                            que.push(pii(v, tk));
                        }
                    }
                }
            }
int main(){
            scanf("%d%d%d%d%d", &n, &m, &s, &t, &k);
            for(int i=1; i<=m; i++) {
                int u,v,w;
                scanf("%d%d%d", &u, &v, &w);
                mp[u].pb(pii(v, w));
                mp[v].pb(pii(u, w));
            }
            bfs(s);
            int ans = inf;
            for(int i=0; i<=k; i++) {
                ans = min(ans, dis[t][i]);
            }
            printf("%d\n", ans);
            return 0;
}
View Code

K

思路:枚舉最后兩個零,看前面有多少個后綴$mod3$等於0。對於$"00"$和$"0"$的情況,最后統計。

代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000000;
int dp[maxn][20];
char ss[maxn];
int main(){
   string ss; cin>>ss; ss="#"+ss;
   int l=ss.size();
   long long  ans=0;
   for(int i=1;i<=l;i++){
       int x=ss[i]-'0';
       dp[i][x%3]++;
       for(int j=0;j<=2;j++){
         dp[i][(j*10+x)%3]+=dp[i-1][j];
       }
       if(i+2 <= l){
          if(ss[i+1]=='0'&&ss[i+2]=='0'){
             ans += dp[i][0];
          }
       }
   }
   for (int i = 1; i <= l; ++i) {
        if(ss[i] == '0') ans++;
        if(i-1 >= 1 && ss[i-1] == '0' && ss[i] == '0') ans++;
   }
   cout<<ans<<endl;
}
View Code

2019牛客暑期多校訓練營(第五場)

題號 標題 團隊的狀態
A digits 2  通過
B generator 1  通過
C generator 2  通過
D generator 3 未通過
E independent set 1  通過
F maximum clique 1  通過
G subsequence 1  通過
H subsequence 2  通過
I three points 1  通過
J three points 2 未通過

A

思路:輸出n個n。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int T, n;
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) printf("%d", n);
        printf("\n");
    }
    return 0;
}
View Code

B

思路:十進制快速冪。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
#define ll long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn=1e6+10;
//head
 
int MOD;
struct Matrix {
    int a[2][2];
    void init() {
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++)
                a[i][j] = 0;
        }
    }
    void _init() {
        init();
        for (int i = 0; i < 2; i++) a[i][i] = 1;
    }
};
 
Matrix mul(Matrix a, Matrix b) {
    Matrix ans;
    ans.init();
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            if(a.a[i][j]) {
                for (int k = 0; k < 2; k++) ans.a[i][k] = (ans.a[i][k] + 1LL * a.a[i][j] * b.a[j][k]) % MOD;
            }
        }
    }
    return ans;
}
Matrix q_pow(Matrix a) {
    Matrix ans;
    ans._init();
    a = mul(a, a);
    ans = mul(ans, a);
    a = mul(a, a);
    a = mul(a, a);
    ans = mul(ans, a);
    return ans;
}
char ss[maxn];
int main() {
    int x0,x1,a,b; scanf("%d %d %d %d",&x0,&x1,&a,&b);
    scanf("%s",ss); scanf("%d",&MOD);
    Matrix c;  c.init(); c.a[0][0]=a;  c.a[0][1]=b; c.a[1][0]=1;  c.a[1][1]=0;
    Matrix d;  d.init(); d.a[0][0]=x1; d.a[0][1]=0; d.a[1][0]=x0; d.a[1][1]=0;
    Matrix x[10];
    for (int i = 0; i < 10; ++i) {
        if(i == 0) x[i]._init();
        else x[i] = mul(x[i-1], c);
    }
    c._init();
    int l = strlen(ss);
    for (int i = 0; i < l; ++i) {
        c = q_pow(c);
        c = mul(c, x[ss[i]-'0']);
    }
    c=mul(c,d);
    printf("%d\n",c.a[1][0]%MOD);
    return 0;
}
View Code

C

思路:BSGS。需要預處理。

隊友代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define LL long long
using namespace std;
int x,a,b;
int p,mod,MOD;
int quick(int x,int n){
    int ans=1;
    while(n){
        if(n&1) ans=1ll* ans*x%mod;
        x=1ll*x*x%mod;  n=n/2;
    } return ans;
}
struct Hash {
    static const int MOD = 1999997;
    static const int N = 1e6;
    int head[MOD + 10], nx[N], top;
    int hs[N], id[N];
    void init() {
        memset(head, -1, sizeof head);
        top = 0;
    }
    void insert(int x, int y) {
        int k = x % MOD;
        hs[top] = x; id[top] = y; nx[top] = head[k]; head[k] = top++;
    }
    int find(int x) {
        int k = x % MOD;
        for (int i = head[k]; i != -1; i = nx[i]) {
            if (hs[i] == x) {
                return id[i];
            }
        }
        return -1;
    }
}hs;
void init(int a,int p){
    int m = pow(p,2.0/3.0)+1, s = 1;  //cout<<m<<endl;
    hs.init();
    for(int i = 0; i < m; ++i){
        hs.insert(s,i);   s= (s*1LL*a)%p;
    }
}
int BSGS(int a, int b, int p){
    int m = pow(p,2.0/3.0)+1, s = b;
    int t = quick(a, m);   int ww=quick(b,mod-2);
    s = 1;
    for(int i = 1; i <= p/m+1; ++i){
        s = (s*1LL*t)%p;   if(hs.find(1ll*s*ww%mod) != -1 ) return i*m-hs.find(1ll*s*ww%mod);
    }
    return -1;
}
int32_t main(){
    int T; scanf("%d",&T);
    while(T--){
            ll n;
        scanf("%lld %d %d %d %d",&n,&x,&a,&b,&p); mod=p; MOD=p;
        int q; scanf("%d",&q); init(a,p);
        while(q--){
            ll y; scanf("%lld",&y);
            if(y==x) { printf("0\n");  continue; }
            if(a==0) {      // x b b b b b
                if(y==b)  printf("1\n");
                else     printf("-1\n");
            }
            else if(a==1){  // x+b x+2*b
                y=((y-x)%mod+mod)%mod;  //cout<<y<<endl;
                y=y*quick(b,mod-2)%mod;
                if(1<=y && y<n ) printf("%lld\n",y);
                else              printf("-1\n");
            }
            else {   //cout<<"---------"<<endl;
                y=( 1ll*(a-1)*y%mod+b)%mod*quick( (1ll*(a-1)*x%mod+b)%mod,mod-2)%mod;
                y=BSGS(a,y,p);
                if(1<=y && y<=n ) printf("%lld\n",y);
                else              printf("-1\n");
            }
        }
    }
 
}
View Code

D

E

思路:狀壓dp。有兩個優化的地方,用char開數組優化空間,從最低位轉移優化時間。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
vector<int> g[26];
int n, m, u, v, st[26];
char dp[(1<<26)+10], mp[(1<<26)+10];
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; ++i) {
        scanf("%d %d", &u, &v);
        st[u] |= 1<<v;
        st[v] |= 1<<u;
    }
    for (int i = 0; i < n; ++i) st[i] |= 1<<i;
    int p = 1;
    for (int i = 0; i < n; ++i) mp[p] = i, p <<= 1;
    dp[0] = 0;
    int up = 1<<n, ans = 0;
    for (int i = 1; i < up; ++i) {
        int x = i&-i;
        dp[i] = max(dp[i], dp[i^x]);
        dp[i] = max(dp[i], (char)(dp[i&(~st[mp[x]])]+1));
        ans += dp[i];
    }
    printf("%d\n", ans);
    return 0;
}
View Code

F

思路:最大團轉換成二分圖最大獨立集。

隊友代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 5e3+9;
            int a[maxn];
            int col[maxn];
            vector<int>L, R;
            vector<int>mp[maxn];
            void dfs(int s, int c) {
                col[s] = c;
                for(int i=0; i<mp[s].size(); i++){
                    int v = mp[s][i];
                    if(col[v] == 0) dfs(v, 3 - c);
                }
            }
            int vis[maxn],match[maxn],pt[maxn];
            bool gkd(int u) {
                if(vis[u]) return false;
                vis[u] = true;
                for(int i = 0; i<mp[u].size(); i++) {
                    int v = mp[u][i];
                    if(match[v] == -1 || gkd(match[v]) ){
                        match[v] = u;
                        pt[u] = v;
                        return true;
                    }
                }
                return false;
            }
            int res[maxn];
            bool findmn(int u) {
                if(u == -1) return false;
                if(res[u]) return true;
                // res[u] = 1;
                if(col[u] == 1){
                     if(findmn(pt[u])) {res[u] = 1;return true;}
                     else return false;

                }
                else {
                    res[u] = 1;
                    for(int i=0; i<mp[u].size(); i++) {
                        int v = mp[u][i];
                        if(match[u] == v) continue;
                        findmn(v);
                    }
                    return true;
                }
            }
int main(){ 
            int n;
            scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%d", &a[i]);
            for(int i=1; i<=n; i++) {
                for(int j=i+1; j<=n; j++) {
                    if(__builtin_popcount(a[i] ^ a[j]) == 1) {
                        mp[i].pb(j);
                        mp[j].pb(i);
                    }
                }
            }

            for(int i=1; i<=n; i++) if(col[i] == 0) dfs(i, 1);
            
            int cnt = 0;
            memset(match, -1, sizeof(match));
            for(int i=1; i<=n; i++) {
                memset(vis, 0, sizeof(vis));
                if(col[i] == 1 && gkd(i)) cnt++;  
            }

            printf("%d\n", n-cnt);
            for(int i=1; i<=n; i++) {
                if(col[i] == 2 && match[i] == -1) {findmn(i);}
            }

            vector<int>ans;
            for(int i=1; i<=n; i++) {
                if(col[i] == 1 && res[i] == 0) ans.pb(a[i]);
                if(col[i] == 2 && res[i] == 1) ans.pb(a[i]);
            }
            for(int i=0; i<ans.size(); i++) {
                printf("%d ", ans[i]);
            }
            puts("");
            return 0;
}
View Code

G

思路:dp。

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e3+10;
const int mod=998244353;
int dp[maxn][maxn];
char ss[maxn];
char tt[maxn];
int A[maxn];
int B[maxn];
int quick(int x,int n){
    int ans=1;
    while(n){
        if(n&1) ans=1ll*ans*x%mod;
        x=1ll*x*x%mod;
        n=n/2;
    } return ans;
}
int C(int n,int x){
    if(x>n) return 0;
    return 1ll*A[n]*B[n-x]%mod*B[x]%mod;
}
int main(){
    A[0]=1; B[0]=1;
    for(int i=1;i<maxn;i++) A[i]=1ll*A[i-1]*i%mod;
    for(int i=1;i<maxn;i++) B[i]=quick(A[i],mod-2);
    //cout<<1ll*121321*1354534<<endl;
    int T; scanf("%d",&T);
    while(T--){
        int ans=0;
        int n,m; scanf("%d %d",&n,&m);
        scanf("%s",ss+1);
        scanf("%s",tt+1);
        dp[0][0]=1;
        for(int i=1;i<=n;i++){
            if(ss[i]!='0'){
                for(int j=m;j<=n-i;j++){
                    ans+=C(n-i,j); ans=ans%mod;
                }
            }
            for(int j=0;j<=m-1;j++) dp[i][j]=dp[i-1][j];
            for(int j=0;j<=m-1;j++){
                if(ss[i]==tt[j+1]) { dp[i][j+1]+=dp[i-1][j]; dp[i][j+1]%=mod; }
                else if(ss[i]>tt[j+1]){
                    ans+=1ll*dp[i-1][j]*C(n-i,m-j-1)%mod; ans=ans%mod;
                }
            }
        }
        printf("%d\n",ans);
        for(int i=0;i<=n+1;i++){
            for(int j=0;j<=m+1;j++){
                dp[i][j]=0;
            }
        }
    }
    return 0;
}
View Code

H

思路:拓撲排序。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include <bits/stdc++.h>
 
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
/**********showtime************/
 
            const int maxn = 1e4+9;
            int vis[22], visno[22];
            char str[5];
            char res[maxn];
            int tot = 0;
            vector<int> mp[22];
            vector<int>G[maxn*100];
            int pt[maxn*100];
            int du[maxn*100];
            int id[maxn];
            char ans[maxn];
int main(){
            int n,m;
            scanf("%d%d", &n, &m);
            int cnt = m * (m - 1) / 2;
            int flag = 1;
            memset(vis, -1, sizeof(vis));
            for(int i=1; i<=cnt; i++) {
                scanf("%s", str);
                int len;    scanf("%d", &len);
                if(len == 0) {
                    int dd1 = str[0] - 'a';
                    int dd2 = str[1] - 'a';
                    visno[dd1] = visno[dd2] = 1;
                    continue;///
                }
 
                scanf("%s", res);
 
                int dd1 = str[0] - 'a';
                int dd2 = str[1] - 'a';
                if(vis[dd1] == -1) {
                    int cc = 0;
                    for(int j = 0; j<len; j++) {
                        if(res[j] == str[0]) {
                            id[j] = ++tot;
                            mp[dd1].pb(tot);
                            pt[tot] = dd1;
                            cc++;
                        }
                    }
                    vis[dd1] = cc;
                }
                else {
                    int cc = 0;
                    for(int j=0; j<len; j++) {
                        if(res[j] == str[0]) {
                            if(cc < mp[dd1].size()) id[j] = mp[dd1][cc];
                            cc++;
                        }
                    }
                    if(cc != vis[dd1])flag = 0;
                 }
 
                 if(vis[dd2] == -1) {
                    int cc = 0;
                    for(int j = 0; j<len; j++) {
                        if(res[j] == str[1]) {
                            id[j] = ++tot;
                            mp[dd2].pb(tot);
                            pt[tot] = dd2;
                            cc++;
                        }
                    }
                    vis[dd2] = cc;
                }
                else {
                    int cc = 0;
                    for(int j=0; j<len; j++) {
                        if(res[j] == str[1]) {
                            if(cc < mp[dd2].size()) id[j] = mp[dd2][cc];
                            cc++;
                        }
                    }
                    if(cc != vis[dd2])flag = 0;
                 }
                 for(int j=0; j<len-1; j++) {
                    G[id[j]].pb(id[j+1]);
                    du[id[j+1]]++;
                 }
            }
 
            for(int i=0; i<m; i++) {
                if(vis[i] && visno[i]) flag = 0;
            }
            if(!flag || tot != n) puts("-1");
            else {
//                string ans = "";
                int all = 0;
                queue<int>que;
                for(int i=1; i<=tot; i++) if(du[i] == 0) que.push(i);
                while(!que.empty()) {
                    int u = que.front(); que.pop();
//                    ans += pt[u] +'a';
                    ans[all++] = pt[u] + 'a';
                    for(int i=0; i<G[u].size(); i++) {
                        int v = G[u][i];
                        du[v]--;
                        if(du[v] == 0) {
                            que.push(v);
                        }
                    }
                }
                int ff = 1;
                for(int i=1; i<=tot; i++) if(du[i] > 0) ff = 0;
                if(ff == 0) puts("-1");
                else {
                    ans[all] = '\0';
                    printf("%s\n",ans);
                }
            }
            return 0;
}
View Code

I

思路:暴力枚舉每條邊的順序關系。

隊友代碼:

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-7;
const double pi=acos(-1.0);
inline double sqr(double x){ return x*x;                                  }
inline int dcmp(double x)  { if(fabs(x)<eps) return 0;return (x>0? 1: -1);}
struct Point{
    double x,y;
    Point(){ x=0,y=0; }
    Point(double _x,double _y):x(_x),y(_y){}
    bool operator ==(const Point &b)const{return  ( dcmp(x-b.x)==0&&dcmp(y-b.y)==0);      }
    bool operator !=(const Point &b)const{return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0));     }
    bool operator <(const Point &b)const {return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x); }
    double operator ^(const Point &b)const{     return x*b.y-y*b.x;}//叉積
    double operator *(const Point &b)const{     return x*b.x+y*b.y;} //點積
    Point operator +(const Point &b)const {     return Point(x+b.x,y+b.y);}
    Point operator -(const Point &b)const {     return Point(x-b.x,y-b.y);}
    Point operator *(double a)            {     return Point(x*a,y*a);    }
    Point operator /(double a)            {     return Point(x/a,y/a);    }
    double len2()                         {     return sqr(x)+sqr(y);     }//長度平方
    double len()                          {      return sqrt(len2());     }//長度
    double polar(){  return atan2(y,x);  }//向量的極角   //返回與x軸正向夾角(-pi~pi]
}X,Y,Z;
double dis(Point A,Point B) { return sqrt( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
struct Circle{
    Point c;
    double r;
    Circle() {c.x=0; c.y=0; r=0; }
    Circle(Point c,double r):c(c),r(r) {}
    Point point(double a){
        return Point (c.x+cos(a)*r,c.y+sin(a)*r);
    }
}A,B;
int h,w,a,b,c;
Point Circle_Cirle(Circle c1, Circle c2){
    double d=dis(c1.c,c2.c);   Point k=c2.c-c1.c;
    double a=k.polar();
    double da=acos( (c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d) );
    Point p1=c1.point(a-da);  //printf("%.10f %.10f\n",p1.x,p1.y);
    Point p2=c1.point(a+da); // printf("%.10f %.10f\n",p2.x,p2.y);
   // cout<<h<<" "<<w<<endl;
    if(-eps<=p1.x && p1.x<=h+eps && p1.y<=w+eps && p1.y>=-eps) return p1;
    if(-eps<=p2.x && p2.x<=h+eps && p2.y<=w+eps && p2.y>=-eps) return p2;
    Point p={-1,-1};
    return p;
}
void make(Point &XX,int aa,Point &YY,int bb,Point &ZZ,int cc){
    XX.x=0; XX.y=0;
    if(aa<=h) { YY.x=aa;  YY.y=0; }
    else      { double qq=sqrt(1.0*aa*aa-1.0*h*h);  YY.x=h; YY.y=qq;  }
    A.c=XX; A.r=cc;
    B.c=YY; B.r=bb;
    ZZ=Circle_Cirle(A,B);
   // cout<<A.c.x<<"  "<<A.c.y<<" "<<A.r<<endl;
   // cout<<B.c.x<<"  "<<B.c.y<<"  "<<B.r<<endl;
  //  printf("%.10f %.10f %.10f %.10f %.10f %.10f\n",abs(X.x),abs(X.y),abs(Y.x),abs(Y.y),abs(Z.x),abs(Z.y));
}
bool check(){
    if( abs(dis(X,Y)-a)<eps && abs(dis(X,Z)-b)<eps && abs(dis(Y,Z)-c)<eps
        && X.x>=-eps  && X.x<=h+eps
        && X.y>=-eps  && X.y<=w+eps
        && Y.x>=-eps  && Y.x<=h+eps
        && Y.y>=-eps  && Y.y<=w+eps
        && Z.x>=-eps  && Z.x<=h+eps
        && Z.y>=-eps  && Z.y<=w+eps
       ) return 1;
        return 0;
}
void work(){
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(X,a,Y,c,Z,b);  if(check()) return ;
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(X,b,Z,c,Y,a);  if(check()) return ;
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Y,a,X,b,Z,c);  if(check()) return ;
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Y,c,Z,b,X,a);  if(check()) return ;
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Z,b,X,a,Y,c);  if(check()) return ;
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Z,c,Y,a,X,b);  if(check()) return ;
}
int main(){
    int T; scanf("%d",&T);
    while(T--){
        scanf("%d %d %d %d %d",&h,&w,&a,&b,&c);
        int flag=0; if(h<w) { swap(h,w); flag=1; }
        work();
        if(flag==1){ swap(X.x,X.y); swap(Y.x,Y.y); swap(Z.x,Z.y); }
        //printf("%.10f\n",dis(X,Y));
        //printf("%.10f\n",dis(X,Z));
        //printf("%.10f\n",dis(Y,Z));
        printf("%.10f %.10f %.10f %.10f %.10f %.10f\n",abs(X.x),abs(X.y),abs(Y.x),abs(Y.y),abs(Z.x),abs(Z.y));
    }
}
View Code

J

2019牛客暑期多校訓練營(第六場)

題號 標題 團隊的狀態
A Garbage Classification  通過
B Shorten IPv6 Address  通過
C Palindrome Mouse  通過
D Move  通過
E Androgynos  通過
F K-ary Heap 未通過
G Is Today Friday?  通過
H Train Driver  通過
I Can They Go to Galar? 未通過
J Upgrading Technology  通過

A

思路:暴力。

代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+10;
char ss[maxn];
char tt[maxn];
map<char,char> mp;
int main(){
    int T; scanf("%d",&T); int tot=0;
    while(T--){
        scanf("%s",ss); int l=strlen(ss);
        scanf("%s",tt); int r=strlen(tt);
        char x='a';
        for(int i=0;i<r;i++) {
            mp[x]=tt[i]; x++;
        }
        int a=0;
        int b=0;
        int c=0;
        for(int i=0;i<l;i++){
            if(mp[ss[i]]=='h') a++;
            if(mp[ss[i]]=='d') b++;
            if(mp[ss[i]]=='w') c++;
        }
        if(4*a>=l){
            printf("Case #%d: Harmful\n",++tot);
        }
        else if(10*a<=l){
             printf("Case #%d: Recyclable\n",++tot);
        }
        else if(b>=2*c){
            printf("Case #%d: Dry\n",++tot);
        }
        else {
            printf("Case #%d: Wet\n",++tot);
        }
        mp.clear();
    }
}
View Code

B

思路:注意如果連續的0在最前面或最后面會少一個冒號。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int T;
string s;
set<string> st;
string x[15];
int l[10];
int main() {
    fio;
    cin >> T;
    for(int cs = 1; cs <= T; ++cs) {
        cin >> s;
        int now = 0;
        for (int i = 0; i < 128; i += 16) {
            string res = "";
            int v = 0;
            for (int j = i; j < i+16; j ++) {
                if(j != i && (j-i)%4 == 0) {
                    if(v == 0) {
                        if(res.size() == 0);
                        else res += '0';
                    }
                    else {
                        if(v >= 10) res += char(v-10+'a');
                        else res += char(v+'0');
                    }
                    v = 0;
                }
                v = v*2+s[j]-'0';
            }
            if(v == 0) {
                if(res.size() == 0);
                else res += '0';
            }
            else {
                if(v >= 10) res += char(v-10+'a');
                else res += char(v+'0');
            }
            if(res.size() == 0) res = "0";
            x[++now] = res;
        }
        int mx = 0;
        for (int i = 1; i <= now; ++i) {
            if(x[i] == "0") l[i] = l[i-1]+1;
            else l[i] = 0;
            mx = max(mx, l[i]);
        }
        if(mx <= 1){
            string t = "";
            for (int i = 1; i <= now; ++i) {
                t += x[i];
                if(i != now) t += ":";
            }
            st.insert(t);
        }
        else {
            for (int i = 1; i <= now; ++i) {
                if(l[i] == mx && i-mx != 0 && i != now) {
                    string t = "";
                    for (int j = 1; j <= i-mx; ++j) {
                        t += x[j];
                        if(j != i-mx) t += ":";
                    }
                    t += "::";
                    for (int j = i+1; j <= now; ++j) {
                        t += x[j];
                        if(j != now) t += ":";
                    }
                    st.insert(t);
                }
            }
            if(st.empty()) {
                for (int i = 1; i <= now; ++i) {
                    if(l[i] == mx) {
                        string t = "";
                        for (int j = 1; j <= i-mx; ++j) {
                            t += x[j];
                            if(j != i-mx) t += ":";
                        }
                        t += "::";
                        for (int j = i+1; j <= now; ++j) {
                            t += x[j];
                            if(j != now) t += ":";
                        }
                        st.insert(t);
                    }
                }
            }
        }
 
        cout << "Case #" << cs << ": "<< *(st.begin()) << "\n";
 
        for (int i = 1; i <= now; ++i) l[i] = 0;
        string().swap(s);
        st.clear();
    }
    return 0;
}
View Code

C

思路:回文自動機上亂跳。

隊友代碼:

#include<bits/stdc++.h>
#define ll long long
#define LL long long
using namespace std;
const int maxn=1e5+10;
char ss[maxn];
struct PAM{
    #define ll long long
    #define LL long long
    static const int maxn=3e5+10;
    static const int num=27;
    int fail[maxn],cnt[maxn],len[maxn],ch[maxn][num],vis[maxn];
    int last,tot;
    LL ans;
    void inint(){
        last=0;  tot=0;
        fail[0]=fail[1]=1;
        len[0]=0; len[1]=-1; tot++; ans=0;
    }
    int get_fail(int p,int pos){
         while(ss[pos-len[p]-1]!=ss[pos]) p=fail[p];
         return p;
    }
    void add(int x,int pos){
        int p=get_fail(last,pos);
        if(!ch[p][x]){
            len[++tot]=len[p]+2;
            fail[tot]=ch[get_fail(fail[p],pos)][x];
            ch[p][x]=tot;
        }
        cnt[last=ch[p][x]]++;
    }
    void count(){  //  bu zhi bu tong hui wen ge shu
        for(int i=tot;i>=0;i--){
            cnt[fail[i]]+=cnt[i];
        }
    }
 
    void clear(){
        for(int i=0;i<=tot;i++){
            fail[i]=0; len[i]=0; cnt[i]=0; vis[i]=0;
            for(int j=0;j<num;j++) ch[i][j]=0;
        }
        last=tot=ans=0;
    }
    void dfs(int u,int s){
        vector<int> vs; //cout<<"---"<<s<<endl;
        for(int i=fail[u];i>=1;i=fail[i]){
            if(vis[i]==1) break;
            s++; vis[i]=1;
            vs.push_back(i);
        }
        ans+=s;// cout<<s<<endl;
        if(vis[u]==0) { vis[u]=1; s++; }
        for(int i=0;i<26;i++){
            if(ch[u][i]){
                dfs(ch[u][i],s);
            }
        }
        if(u!=0 && u!=1) vis[u]=0;
        for(int i=0;i<vs.size();i++) vis[vs[i]]=0;
    }
    void work(){
        vis[0]=1;  vis[1]=1;  //cout<<ans<<endl;
        dfs(0,0);
        dfs(1,0);
    }
}pam;
int main(){
    int T; scanf("%d",&T);  int tot=0;
    while(T--){
        scanf("%s",ss);  int l=strlen(ss);
        pam.inint();
        for(int i=0;i<l;i++) pam.add(ss[i]-'a',i);
        pam.work();
        printf("Case #%d: %lld\n",++tot,pam.ans);
        pam.clear();
    }
 
}
View Code

D

思路:算一個下界,暴力計算。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e3 + 5;
vector<int> vc;
int v[N], T, n, k;
multiset<int> a, b;
int main() {
    scanf("%d", &T);
    for (int cs = 1; cs <= T; ++cs) {
        scanf("%d %d", &n, &k);
        for (int i = 1; i <= n; ++i) scanf("%d", &v[i]), a.insert(v[i]);
        int sum = 0, mx = 0;
        for (int i = 1; i <= n; ++i) sum += v[i], mx = max(mx, v[i]);
        int dw = max(mx, (sum+k-1)/k);
        for (int i = dw; ; ++i) {
            int tt = 0, now = 0, up = i;
            b = a;
            while(!b.empty()) {
                auto t = b.upper_bound(up-now);
                if(t == b.begin()) {
                    now = 0;
                    ++tt;
                }
                else {
                    --t;
                    now += *t;
                    b.erase(b.find(*t));
                }
            }
            if(now) ++tt;
            if(tt <= k) {
                printf("Case #%d: %d\n", cs, up);
                break;
            }
        }
 
        a.clear();
        b.clear();
    }
    return 0;
}
View Code

E

思路:4個一起構造,最后如果剩下5個單獨構造。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include <bits/stdc++.h>
 
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
/**********showtime************/
 
            const int maxn = 2009;
            int mp[maxn][maxn];
            int pt[maxn];
 
            void solve(int le, int ri) {
                if(ri - le + 1 == 5) {
                    for(int i=le; i<ri; i++) {
                        mp[i+1][i] = mp[i][i+1] = 1;
                        pt[i] = i+1;
                    }
                    mp[le][ri] = mp[ri][le] = 1;
                    pt[le] = le;
                    pt[le+1] = le+2;
                    pt[ri] = ri-1;
                    pt[le+2] = ri;
                    pt[le+3] = le+1;
                }
                else if(ri - le + 1 == 4) {
                    mp[le][le+2] = mp[le+2][le] = 1;
                    mp[le][le+1] = mp[le+1][le] = 1;
                    mp[le+1][le+3] = mp[le+3][le+1] = 1;
                    pt[le] = le + 2;
                    pt[le+1] = le + 3;
                    pt[le+2] = le+1;
                    pt[le+3] = le;
                }
                else {
                    mp[le][le+2] = mp[le+2][le] = 1;
                    mp[le][le+1] = mp[le+1][le] = 1;
                    mp[le+1][le+3] = mp[le+3][le+1] = 1;
                    pt[le] = le + 2;
                    pt[le+1] = le + 3;
                    pt[le+2] = le+1;
                    pt[le+3] = le;
                    for(int i= le+4; i<=ri; i++) {
                        mp[le+2][i] = 1;
                        mp[i][le+2] = 1;
 
                        mp[le+3][i] = 1;
                        mp[i][le+3] = 1;
                    }
                    solve(le+4, ri);
                }
            }
int main(){
            int T;  scanf("%d", &T);
            int cas = 0;
            while(T--) {
                int n;  scanf("%d", &n);
                if(n == 1) {
                    printf("Case #%d: Yes\n", ++cas);
                    printf("0\n1\n");
                }
                else if(n < 4)
                    printf("Case #%d: No\n", ++cas);
                else {
                    if(n * (n-1) % 4)
                            printf("Case #%d: No\n", ++cas);
                    else {
                        printf("Case #%d: Yes\n", ++cas);
                        for(int i=1; i<=n; i++) {
                            for(int j=1; j<=n; j++) mp[i][j] = 0;
                            pt[i] = 0;
                        }
                        solve(1, n);
                        for(int i=1; i<=n; i++) {
                            for(int j=1; j<=n; j++) {
                                printf("%d",mp[i][j]);
                            }
                            puts("");
                        }
                        for(int i=1; i<n; i++) printf("%d ", pt[i]);
                        printf("%d\n", pt[n]);
                    }
                }
            }
            return 0;
}
View Code

F

G

思路:暴力枚舉排列,然后判斷每一個是否可以(用蔡勒公式),由於存在的情況很少,所以判斷只要很少就能退出。除了一種情況,一直都是可以的,

但是本質不同的可以的很少,所以這種情況肯定有很多重復的。所以暴力前先去個重。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int T, n;
vector<string> s;
int a[10];
int month[2][12] = {
    {31,28,31,30,31,30,31,31,30,31,30,31},
    {31,29,31,30,31,30,31,31,30,31,30,31}
};
inline bool ck(int x) {
    return (x%4==0&&x%100!=0) || x%400==0;
}
inline int caile(int x, int y, int z) {
    if(x < 1600) return 0;
    if(y > 12 || y == 0) return 0;
    if(ck(x)) {
        if(z == 0 || z > month[1][y-1]) return 0;
    }
    else {
        if(z == 0 || z > month[0][y-1]) return 0;
    }
    if(y <= 2) y += 12, x--;
    return ((x/100/4-2*(x/100)+x%100+x%100/4+26*(y+1)/10+z-1)%7+7)%7;
}
int main() {
    fio;
    cin >> T;
    for (int cs = 1; cs <= T; ++cs) {
        cin >> n;
        s.resize(n);
        for (int i = 0; i < n; ++i) cin >> s[i];
        sort(s.begin(), s.end());
        s.erase(unique(s.begin(), s.end()), s.end());
        for (int i = 0; i < 10; ++i) a[i] = i;
        bool ok = false;
        do {
            bool f = true;
            for (int i = 0; i < s.size(); ++i) {
                int x = 0, y = 0, z = 0;
                for (int j = 0; j < 4; ++j) x = x*10 + a[s[i][j]-'A'];
                for (int j = 5; j < 7; ++j) y = y*10 + a[s[i][j]-'A'];
                for (int j = 8; j < 10; ++j) z = z*10 + a[s[i][j]-'A'];
                if(caile(x, y, z) == 5) ;
                else {
                    f = false;
                    break;
                }
            }
            if(f)  {
                ok = true;
                cout << "Case #" << cs << ": ";
                for (int i = 0; i < 10; ++i) cout << a[i];
                cout << "\n";
                break;
            }
            else continue;
        }while(next_permutation(a, a+10));
        if(!ok)  cout << "Case #" << cs << ": Impossible\n";
    }
    return 0;
}
View Code

H

思路:先用bfs預處理每個$a$集合和$b$集合的點到其他點的最短距離。然后枚舉$a$集合的點$x$和$b$集合的點$y$,把每個點到$x$的距離和到$y$的距離加起來作為初始值,

然后來更新其他點的最短距離,由於不能有$logn$的復雜度,所以要先對距離哈希排序,然后用兩個隊列來更新,每次取兩個隊列隊首最小值更新。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
int T, n, m, u, v;
vector<int> g[N], vc[N*2];
int a[22], b[22], da[22][N], db[22][N], ca, cb;
int q[N*2], l1, r1, l2, r2, dis[N];
pii q1[N*2], q2[N*2];
inline void bfs(int u, int *dis) {
    for (int i = 1; i <= n; ++i) dis[i] = -1;
    dis[u] = 0;
    int l = 1, r = 0;
    q[++r] = u;
    while(l <= r) {
        int u = q[l++];
        for (int v : g[u]) {
            if(~dis[v]) ;
            else dis[v] = dis[u]+1, q[++r] = v;
        }
    }
}
inline LL solve(int x, int y) {
    LL ans = 0;
    for (int i = 1; i <= n; ++i) vc[da[x][i]+db[y][i]].pb(i), dis[i] = -1;
    int l1 = 1, r1 = 0, l2 = 1, r2 = 0;
    for (int i = 0; i <= 2*n; ++i) {for (int u : vc[i]) q1[++r1] = {i, u}; vc[i].clear();}
    while(l1 <= r1 || l2 <= r2) {
        if(l1 <= r1 && l2 <= r2) {
            if(q1[l1].fi < q2[l2].fi) {
                int d = q1[l1].fi, u = q1[l1].se;
                ++l1;
                if(~dis[u]) continue;
                dis[u] = d;
                for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v};
            }
            else {
                int d = q2[l2].fi, u = q2[l2].se;
                ++l2;
                if(~dis[u]) continue;
                dis[u] = d;
                for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v};
            }
        }
        else if(l1 <= r1) {
            int d = q1[l1].fi, u = q1[l1].se;
            ++l1;
            if(~dis[u]) continue;
            dis[u] = d;
            for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v};
        }
        else {
            int d = q2[l2].fi, u = q2[l2].se;
            ++l2;
            if(~dis[u]) continue;
            dis[u] = d;
            for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v};
        }
    }
    for (int i = 1; i <= n; ++i) ans += dis[i];
    return ans;
}
int main() {
    scanf("%d", &T);
    for (int cs = 1; cs <= T; ++cs) {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= m; ++i) scanf("%d %d", &u, &v), g[u].pb(v), g[v].pb(u);
        scanf("%d", &ca); for (int i = 1; i <= ca; ++i) scanf("%d", &a[i]);
        scanf("%d", &cb); for (int i = 1; i <= cb; ++i) scanf("%d", &b[i]);
        for (int i = 1; i <= ca; ++i) bfs(a[i], da[i]);
        for (int i = 1; i <= cb; ++i) bfs(b[i], db[i]);
        LL ans = 0;
        for (int i = 1; i <= ca; ++i) {
            for (int j = 1; j <= cb; ++j) {
                LL t = solve(i, j);
                ans += t;
            }
        }
        LL d = ca*1LL*cb*1LL*n;
        LL dd = __gcd(d, ans);
        d /= dd, ans /= dd;
        printf("Case #%d: %lld/%lld\n", cs, ans, d);
        for (int i = 1; i <= n; ++i) g[i].clear();
    }
    return 0;
}
View Code

I

J

思路:注意如果要最多達到$level_i$,至少有一個技能正好是$lelel_i$。

代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-02 20:30:39
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-02 22:33:17
*/
// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
            const int maxn = 1009;
            ll a[maxn][maxn];
            ll sum[maxn][maxn];
            ll ss[maxn][maxn];
            ll b[maxn];
int main(){
            int T;  scanf("%d", &T);
            int cas = 0;
            while(T--) {
                int n,m;
                scanf("%d%d", &n, &m);
                for(int i=1; i<=n; i++) {
                    for(int j=1; j<=m; j++) {
                        scanf("%lld", &a[i][j]);
                    }
                }
                for(int i=0; i<=n; i++) {
                    for(int j=0; j<=m; j++) {
                        sum[i][j] = ss[i][j] = 0;
                    }
                }
                for(int i=1; i<=m; i++) scanf("%lld", &b[i]);
                for(int i=1; i<=n; i++) {
                    for(int j=1; j<=m; j++) sum[i][j] = sum[i][j-1] + a[i][j], ss[i][j] = sum[i][j];
                    for(int j=m-1; j>=0; j--) sum[i][j] = min(sum[i][j], sum[i][j+1]);
                }
                ll ans = 0, allb = 0;
                for(int i=0; i<=m; i++) {
                    ll tmp = 0;
                    allb += b[i];
                    for(int j=1; j<=n; j++) {
                        tmp += sum[j][i];
                    }
                    for(int j=1; j<=n; j++) {
                        tmp -= sum[j][i];
                        tmp += ss[j][i];
                        ans = max(ans, allb - tmp);
                        tmp += sum[j][i];
                        tmp -= ss[j][i];
                    }
                }
                printf("Case #%d: %lld\n",++cas,  ans);
            }
            return 0;
}
View Code 

2019牛客暑期多校訓練營(第七場)

題號 標題 團隊的狀態
A String  通過
B Irreducible Polynomial  通過
C Governing sand  通過
D Number  通過
E Find the median  通過
F Energy stones 未通過
G Make Shan Happy 未通過
H Pair  通過
I Chessboard 未通過
J A+B problem  通過
K Function 未通過

A

思路:$O(n^3)$的dp加最小表示法。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
string s;
int Min(string s) {
    int i = 0, j = 1, k = 0, n = s.size(), d;
    while(i < n && j < n && k < n) {
        d = s[(i+k)%n] - s[(j+k)%n];
        if(!d) k++;
        else {
            if(d > 0) i += k+1;
            else j += k+1;
            if(i == j) j++;
            k = 0;
        }
    }
    return min(i, j);
}
const int N = 222;
int T, dp[N], pre[N], can[N][N];
int main() {
    fio;
    cin >> T;
    while(T--) {
        cin >> s;
        int n = s.size();
        for (int i = 0; i <= n; ++i) dp[i] = 2*n;
        for (int i = 1; i <= n; ++i) {
            string t = "";
            for (int j = i; j <= n; ++j) {
                t += s[j-1];
                if(Min(t) == 0) can[i][j] = 1;
                else can[i][j] = 0;
            }
        }
        dp[0] = 1;
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j < i; ++j) {
                if(dp[j] && can[j+1][i] && dp[j]+1 <= dp[i]) {
                    dp[i] = dp[j]+1;
                    pre[i] = j;
                }
            }
        }
        vector<int> vc;
        int now = n;
        vc.pb(n);
        while(pre[now]) {
            now = pre[now];
            vc.pb(now);
        }
        vc.pb(0);
        reverse(vc.begin(), vc.end());
        for (int i = 1; i < vc.size(); ++i) {
            for (int j = vc[i-1]; j < vc[i]; ++j) cout << s[j];
            if(i+1 != vc.size())cout << " ";
        }
        cout << endl;
    }
    return 0;
}
View Code

B

思路:因為三次及以上實系數多項式至少有一個實零點,所以它可以分解。

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=13;
int a[maxn];
int main(){
    int T; scanf("%d",&T);
    while(T--){
        int n; scanf("%d",&n);
        for(int i=n;i>=0;i--){
            scanf("%d",&a[i]);
        }
        if(n>2) printf("No\n");
        else if(n<2) printf("Yes\n");
        else {
            long long c=a[1]*a[1]-4*a[2]*a[0];
            if(c<0) printf("Yes\n");
            else printf("No\n");
        }
    }
}
View Code

C

思路:暴力

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
 
            const int maxn = 1e5+9;
            struct E{
                ll h,c,p;
            }a[maxn];
            bool cmp(E a, E b) {
                return a.h < b.h;
            }
            ll sum[maxn];
            ll jilu[209];
int main(){
            int n;
            while(~scanf("%d", &n)) {
                ll ans = inff;
                for(int i=1; i<=n; i++) {
                    scanf("%lld%lld%lld", &a[i].h, &a[i].c, &a[i].p);
                }
                sort(a+1, a+1+n, cmp);
                sum[n+1] = 0;
                for(int i=n; i>=1; i--) {
                    sum[i] = sum[i+1] + 1ll*a[i].c * a[i].p;
                }
                for(int i=0; i<209; i++) jilu[i] = 0;
                a[n+1].h = inf;
                int las = 1;
                ll cnt = 0;
                for(int i=1; i<=n; i++) {
                    if(a[i].h < a[i+1].h) {
                        cnt += a[i].p;
                        ll tmp = sum[i+1];
                        ll baoliu = 0;
                        ll cc = cnt - 1;
                        for(int j=202; j>=0 && cc; j--) {
                            ll yong = min(jilu[j], cc);
                            baoliu += yong * j;
                            cc -= yong;
                        }
                        tmp = tmp + sum[1] - sum[las] - baoliu;
//                        debug(tmp);
                        ans = min(ans, tmp);
 
                        for(int j=las; j<=i; j++)
                            jilu[a[j].c] += a[i].p;
                        las = i+1;
                        cnt = 0;
                    }
                    else {
                        cnt += a[i].p;
                    }
                }
                printf("%lld\n", ans);
            }
            return 0;
}
View Code

D

思路:看位數夠不夠,夠的話輸出一個,后面補0,否則就是不可以。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
LL n, p;
int main() {
    scanf("%lld %lld", &n, &p);
    LL t = p;
    int cnt = 0;
    while(t) t /= 10, ++cnt;
    if(n >= cnt) {
        for (int i = 0; i < n/cnt; ++i) printf("%lld", p);
        for (int i = 0; i < n%cnt; ++i) printf("0");
        printf("\n");
    }
    else printf("T_T\n");
    return 0;
}
View Code

E

思路:離散化+線段樹

代碼:

#pragma GCC optimize(2)
 #pragma GCC optimize(3)
 #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
  
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
  
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
  
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
  
/**********showtime************/
            const int big = 1e9;
            const int maxn = 400005;
            int X[maxn],Y[maxn];
            int L[maxn], R[maxn];
            int a1,b1,c1,m1;
            int a2,b2,c2,m2;
            struct node{
                int cnt;
                ll sum;
                int lazy;
                int len;
            } tree[maxn * 8];
            vector<int>vec;
            int getid(int x) {
                return lower_bound(vec.begin(), vec.end(), x) - vec.begin() + 1;
            }
 
 
            void pushdown(int le,int ri,int rt) {
                tree[rt<<1].cnt += tree[rt].lazy;
                tree[rt<<1|1].cnt += tree[rt].lazy;
                tree[rt<<1].lazy += tree[rt].lazy;
                tree[rt<<1|1].lazy += tree[rt].lazy;
                int mid = (le + ri) >> 1;
 
                tree[rt<<1].sum +=  1ll*tree[rt].lazy * (vec[mid] - vec[le-1]);
                tree[rt<<1|1].sum +=  1ll*tree[rt].lazy *(vec[ri] - vec[mid]);
                tree[rt].lazy = 0;
            }
 
             
            void update(int L, int R, int le, int ri, int rt) {
                if(le >= L && ri <= R) {
                    tree[rt].lazy++;
                    tree[rt].cnt++;
                    tree[rt].sum += 1ll*(vec[ri] - vec[le - 1]);
                    return;
                }
                int mid = (le + ri) >> 1;
                if(tree[rt].lazy) pushdown(le,ri,rt);
                if(mid >= L) {
                    update(L, R, le, mid, rt<<1);
                }
                if(mid < R) {
                    update(L, R, mid+1, ri, rt<<1|1);
                }
                tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
            }
 
            int query(ll tot, int le, int ri, int rt) {
                if(le == ri) {
 
                    int cnt = tree[rt].cnt, res;
                    int lbound = vec[le-1];
                    if(tot % cnt == 0) {
                        res = lbound + tot / cnt - 1;
                    }
                    else
                        res = lbound + tot / cnt;
                    return res;
 
                }
  
                int mid = (le + ri) >> 1;
                if(tree[rt].lazy) pushdown(le,ri,rt);
  
                ll lsum = tree[rt<<1].sum;
                if(lsum >= tot) return query(tot,le, mid, rt<<1);
                else return query(tot - lsum, mid+1, ri, rt<<1|1);
            }
int main(){
  
            int n;
            scanf("%d", &n);
            scanf("%d%d%d%d%d%d", &X[1], &X[2], &a1, &b1, &c1, &m1);
            scanf("%d%d%d%d%d%d", &Y[1], &Y[2], &a2, &b2, &c2, &m2);
             
            L[1] = min(X[1], Y[1]) + 1;
            R[1] = max(X[1], Y[1]) + 1;
            L[2] = min(X[2], Y[2]) + 1;
            R[2] = max(X[2], Y[2]) + 1;
            R[1] ++; R[2] ++;
            vec.pb(L[1]);vec.pb(R[1] );
            vec.pb(L[2]);vec.pb(R[2]);
            for(int i=3; i<=n; i++) {
                X[i] = (1ll*a1 * X[i-1] + 1ll*b1 * X[i-2] + c1 )% m1;
                Y[i] = (1ll*a2 * Y[i-1] + 1ll*b2 * Y[i-2] + c2 )% m2;
                L[i] = min(X[i], Y[i]) + 1;
                R[i] = max(X[i], Y[i]) + 1;
                R[i] ++;
                vec.pb(L[i]);   vec.pb(R[i]);
            }
            sort(vec.begin(), vec.end());
            vec.erase(unique(vec.begin(), vec.end()), vec.end());
            for(int i=1; i<=n; i++) {
                L[i] = getid(L[i]);
                R[i] = getid(R[i]);
            }
             
            int tot = vec.size();
 
            ll all = 0;
 
            for(int i=1; i<=n; i++) {
                 
                update(L[i], R[i] - 1, 1, tot, 1);
 
                all += 1ll*(vec[R[i]-1] - vec[L[i] - 1]);
                 
                printf("%d\n", query((all + 1)/2, 1, tot, 1));
            }
            return 0;
}
View Code

F

G

H

思路:數位dp

代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-09 23:58:00
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-10 22:19:16
* @Link https://ac.nowcoder.com/acm/contest/887/H
*/
// #pragma GCC optimize(2)
//  #pragma GCC optimize(3)
//  #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
   
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
   
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
   
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
   
/**********showtime************/
            ll dp[35][2][2][2][2][3][3];
            //dp[len][limit1][limit2][ok1][ok2]
            //由於兩個數要大於0,所以多加上ok1,ok2.
            //f1 &的, f2 ^的
            int shuA[35],shuB[35],shuC[35];
            ll dfs(int len, int limit1, int limit2, int ok1, int ok2, int f1, int f2){
                if(f1 == 2 && f2 == 2) return 0;
                if(dp[len][limit1][limit2][ok1][ok2][f1][f2] != -1)
                    return dp[len][limit1][limit2][ok1][ok2][f1][f2];
                if(len == 0) {
                    return ok1 && ok2 && (f1 == 1 || f2 == 1);
                } 
  
                int up1 = 1, up2 = 1;
                if(limit1) up1 = shuA[len];
                if(limit2) up2 = shuB[len];
                ll res = 0;
                // cout<<len<<" " << up1<<" , " << up2<<endl;
                for(int i=0; i<=up1; i++) {
                    for(int j=0; j<=up2; j++) {
                          
                        // if(len == 2)cout<<len << " " << i << " , " << j << "  = " << f1 <<" , , " <<f2 << endl;
  
                        if(f1 == 1 || f2 == 1) res += dfs(len-1, limit1 && i == up1, limit2 && j == up2, ok1 || i, ok2 || j, f1, f2);
                        else {
                            int F1 = f1, F2 = f2;
                            if((i & j) < shuC[len]) F1 = 2;
                            else if((i & j) > shuC[len]) F1 = max(F1, 1);
  
                            if((i ^ j) > shuC[len]) F2 = 2;
                            else if((i ^ j) < shuC[len]) F2 = max(F2, 1);
                            res += dfs(len-1, limit1 && i == up1, limit2 && j == up2, ok1 || i, ok2 || j, F1, F2);
                        } 
                    }
  
                }
                dp[len][limit1][limit2][ok1][ok2][f1][f2] = res;
                return res;
            }
  
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                int a, b, c;
                scanf("%d%d%d", &a, &b, &c);
                memset(dp, -1, sizeof(dp));
                int len = 32;
                for(int i=1; i<=len; i++) shuA[i] = a % 2, a = a >> 1;
                 for(int i=1; i<=len; i++) shuB[i] = b % 2, b = b >> 1;
                for(int i=1; i<=len; i++) shuC[i] = c % 2, c = c >> 1;
                printf("%lld\n", dfs(len, 1, 1, 0, 0, 0, 0));
            }
            return 0;
}
View Code

I

J
思路:水題

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
 
            const int maxn = 50009;
            int p[maxn], a[maxn];
            int ans[maxn];
            int shu[maxn];
            ll f(ll val) {
                int len = 0;
                while(val > 0 && val % 10 == 0) val /= 10;
                while(val > 0) {
                    shu[++len] = val % 10;
                    val = val / 10;
                }
                ll res = 0;
                for(int i=1; i<=len; i++) {
                    res = res * 10 + shu[i];
                }
                return res;
            }
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                ll a, b;
                scanf("%lld%lld", &a, &b);
                printf("%lld\n", f(f(a) + f(b)));
            }
            return 0;
}
View Code

K

2019牛客暑期多校訓練營(第八場)

題號 標題 團隊的狀態
A All-one Matrices  通過
B Beauty Values  通過
C CDMA  通過
D Distance  通過
E Explorer  通過
F Flower Dance  通過
G Gemstones  通過
H How Many Schemes 未通過
I Inner World  通過
J Just Jump  通過

A

思路:一個左上角的點和右邊界三個值可以確定一個矩陣,然后unorded_map去重被卡,最后用手寫bitmap過了(因為bool是一個字節的開不下,bitset也開不下)。正解是單調棧。

bitmap代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
  
const int N = 3e3 + 5;
const int MOD = 2e9 + 7;
short l[N][N], r[N][N], up[N][N];
int n, m;
class BitMap {
public:
    BitMap(int num):n(num),mask(0x1F),shift(5),pos(1<<mask),a(1+n/32,0){}
    void set(int i) {
        a[i>>shift] |= (pos>>(i & mask));
    }
    int get(int i) {
        return a[i>>shift] & (pos>>(i & mask));
    }
    void clr(int i) {
        a[i>>shift] &= ~(pos>>(i & mask));    
    }  
private:
    int n;
    const int mask;
    const int shift;
    const unsigned int pos;
    vector<unsigned int> a;
};
char s[N][N];
BitMap vis(MOD);
int main() {
    scanf("%d %d",&n, &m);
    for (int i = 1; i <= n; ++i) scanf("%s", s[i]+1);
     for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if(s[i][j] == '1') l[i][j] = l[i][j-1]+1;
        }
        for (int j = m; j >= 1; --j) {
            if(s[i][j] == '1') r[i][j] = r[i][j+1]+1;
        }
    }
    int ans = 0;
     
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if(s[i][j] == '1') {
                up[i][j] = up[i-1][j]+1;
                if(s[i-1][j] == '1') {
                    l[i][j] = min(l[i-1][j], l[i][j]);
                    r[i][j] = min(r[i-1][j], r[i][j]);
                }
                LL X = i-up[i][j]+1, Y = j-l[i][j]+1, Z = j+r[i][j]-1;
                LL t = (X*3021*3021+Y*3021+Z)%MOD;
                //cout << X << " "<< Y << " " << Z << endl;
                if(!vis.get(t)) vis.set(t), ans++;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}
View Code

正解代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
 
            const int maxn = 3009;
            char str[maxn][maxn];
            int sum[maxn][maxn];
            int dp[maxn][maxn];
            int ls[maxn];
            stack<pii>st;
int main(){
            int n,m;
            scanf("%d%d", &n, &m);
            for(int i=1; i<=n; i++) scanf("%s", str[i] + 1);
            for(int i=1; i<=n; i++) {
                for(int j=1; j<=m; j++) {
                    sum[i][j] = sum[i][j-1];
                    if(str[i][j] == '1') sum[i][j] ++;
                }
            }
 
            for(int i=n; i>=1; i--) {
                for(int j=1; j<=m; j++) {
                    if(str[i][j] == '1') dp[i][j] = dp[i+1][j] + 1;
                    else dp[i][j] = 0;
                }
            }
 
            int ans = 0;
            for(int i=1; i<=n; i++) {
//                debug(i);
                while(!st.empty()) st.pop();
                st.push(pii(-1, 0));
                for(int j=1; j<=m; j++) {
                        while(!st.empty() && st.top().fi >= dp[i][j]) {
                            st.pop();
                        }
                        ls[j] = st.top().se + 1;
                        st.push(pii(dp[i][j], j));
                }
                while(!st.empty()) st.pop();
                 for(int j=1; j<=m + 1; j++) {
                    while(!st.empty() && st.top().fi > dp[i][j]) {
                        int le = ls[st.top().se], ri = j - 1;
                        st.pop();
                        if(sum[i-1][ri] - sum[i-1][le-1] == ri - le + 1) continue;
                        ans++;
                    }
                    if(j < m + 1 && (st.empty() || dp[i][j] > st.top().fi) )st.push(pii(dp[i][j], j));
                }
 
            }
            printf("%d\n", ans);
            return 0;
}
View Code

B

思路:考慮每個位置的貢獻

代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-10 12:07:44
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-10 12:14:56
*/
// #pragma GCC optimize(2)
//  #pragma GCC optimize(3)
//  #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
  
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
  
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
  
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
  
/**********showtime************/
 
            const int maxn = 1e5+9;
            int a[maxn];
            int pre[maxn], las[maxn];
            int le[maxn],ri[maxn];
int main(){
            int n; 
            scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%d", &a[i]), las[i] = n + 1;
            ll sum = 0;
            for(int i=1; i<=n; i++) {
                le[i] = pre[a[i]] + 1;
                sum = sum + 1ll*(i - le[i] + 1) * (n - i + 1);
                pre[a[i]] = i;
            }
            printf("%lld\n", sum);
            return 0;
}
View Code

C

思路:構造。左上角、右上角、左下角原矩陣,右下角相反矩陣。cf原題。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int dp[1055][1055];
int main() {
    dp[0][0]=1;
    int t=10;
    int c=1;
    while(t--) {
        for(int i=0;i<c;i++) {
            for(int j=0;j<c;j++) {
                dp[i][j+c]=dp[i][j];
                dp[i+c][j]=dp[i][j];
                dp[i+c][j+c]=-dp[i][j];
            }
        }
        c<<=1;
    }
    int m;
    scanf("%d", &m);
    for (int i = 0; i < m; ++i) {
        for(int j = 0; j < m; ++j) printf("%d%c", dp[i][j], " \n"[j+1==m]);
    }
    return 0;
}
View Code

D

思路:定期重構

隊友代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-11 21:48:52
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-11 23:23:57
*/
 
// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<int, pii> p3;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
 
            const int maxn = 1e5+9;
            int n,m,h,q;
            int getid(int x, int y, int z) {
                return (z - 1)* (n * m) + (x-1)*m + y;
            }
            vector<int>vx,vy,vz;
            int dis[maxn];
            int xia[8][3] = {{0,0,1},{0,1,0},{1,0,0}, {-1, 0 ,0 }, {0, -1 ,0 }, {0, 0 ,-1 }};
            void rebuild(){
                queue< p3>que;
                for(int i=0; i<vx.size(); i++) {
                        int nx = vx[i];
                        int ny = vy[i];
                        int nz = vz[i];
                        dis[getid(nx, ny, nz)] = 0;
                        que.push(p3(nx, pii(ny, nz)));
                }
                vx.clear();
                vy.clear();
                vz.clear();
                while(!que.empty()) {
                    p3 tmp = que.front(); que.pop();
                    int x = tmp.fi;
                    int y = tmp.se.fi;
                    int z = tmp.se.se;
                    for(int i=0; i<6; i++) {
                        int nx = x + xia[i][0];
                        int ny = y + xia[i][1];
                        int nz = z + xia[i][2];
                        if(nx <= 0 || nx > n || ny <= 0|| ny > m || nz <= 0 || nz > h) continue;
                        if(dis[getid(nx, ny, nz)] > dis[getid(x, y, z)] + 1) {
                            dis[getid(nx, ny, nz)] = dis[getid(x, y, z)] + 1;
                            que.push(p3(nx, pii(ny, nz)));
                        }
                    }
                }
 
            }
int main(){
            scanf("%d%d%d%d", &n, &m, &h, &q); 
            int E = sqrt(n * m * h) + 1;
            memset(dis, inf, sizeof(dis));
 
            while(q--) {
                int op, x, y, z;
                scanf("%d%d%d%d", &op, &x, &y, &z);
                if(op == 1) {
                    vx.pb(x);
                    vy.pb(y);
                    vz.pb(z);
                }
                else {
                    int ans = dis[getid(x, y, z)];
                    for(int i=0; i<vx.size(); i++) {
                        int nx = vx[i];
                        int ny = vy[i];
                        int nz = vz[i];
                        ans = min(ans, abs(nx - x) + abs(ny - y) + abs(nz - z));
                    }
                    printf("%d\n", ans);
                }
                if(vx.size() >= E) rebuild();
            }
            return 0;
}
View Code

E

思路:按sz分治,把邊按sz放到划分樹上,然后分治,用可撤銷並查集維護連通性。和P2147 [SDOI2008]洞穴勘測類似。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
struct UFS {
    stack<pair<int*, int>> stk;
    int fa[N], rnk[N];
    inline void init(int n) {
        for (int i = 0; i <= n; ++i) fa[i] = i, rnk[i] = 0;
    }
    inline int Find(int x) {
        while(x^fa[x]) x = fa[x];
        return x;
    }
    inline void Merge(int x, int y) {
        x = Find(x), y = Find(y);
        if(x == y) return ;
        if(rnk[x] <= rnk[y]) {
            stk.push({fa+x, fa[x]});
            fa[x] = y;
            if(rnk[x] == rnk[y]) {
                stk.push({rnk+y, rnk[y]});
                rnk[y]++;
            }
        }
        else {
            stk.push({fa+y, fa[y]});
            fa[y] = x;
        }
    }
    inline void Undo() {
        *stk.top().fi = stk.top().se;
        stk.pop();
    }
}ufs;
struct Node {
    int u, v, l, r;
}a[N];
int n, m, ans;
vector<pii> vc[N<<3];
vector<int> vv;
void update(int L, int R, pii p, int rt, int l, int r) {
    if(L <= l && r <= R) {
        vc[rt].pb(p);
        return ;
    }
    int m = l+r >> 1;
    if(L <= m) update(L, R, p, ls);
    if(R > m)  update(L, R, p, rs);
}
inline int get_id(int x) {
    return lower_bound(vv.begin(), vv.end(), x)-vv.begin();
}
void dfs(int rt, int l, int r) {
    int sz = ufs.stk.size();
    for (pii p : vc[rt]) ufs.Merge(p.fi, p.se);
    if(l == r){
        if(ufs.Find(1) == ufs.Find(n)) ans += vv[l+1]-vv[l];
        while(ufs.stk.size() > sz) ufs.Undo();
        return ;
    }
    int m = l+r >> 1;
    dfs(ls);
    dfs(rs);
    while(ufs.stk.size() > sz) ufs.Undo();
}
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; ++i) scanf("%d %d %d %d", &a[i].u, &a[i].v, &a[i].l, &a[i].r), ++a[i].r, vv.pb(a[i].l), vv.pb(a[i].r);
    sort(vv.begin(), vv.end());
    vv.erase(unique(vv.begin(), vv.end()), vv.end());
    int tot = vv.size();
    for (int i = 1; i <= m; ++i) {
        update(get_id(a[i].l), get_id(a[i].r)-1, {a[i].u, a[i].v}, 1, 0, tot-2);
    }
    ufs.init(n);
    dfs(1, 0, tot-2);
    printf("%d\n", ans);
    return 0;
}
View Code

F

思路:枚舉中心點,然后極角排序,然后將中心點看成原點,然后三角形的三個點只有兩種情況:x軸上面2個點,下面1個點,x軸上面1個點,下面2個點

隊友代碼:

#include<bits/stdc++.h>
using namespace std;
struct Point{
    double x,y;
    double t;
    Point(){ x=0,y=0; }
    Point(double _x,double _y):x(_x),y(_y){}
    double operator ^(const Point &b)const{     return x*b.y-y*b.x;}//叉積
    double operator *(const Point &b)const{     return x*b.x+y*b.y;} //點積
    Point operator +(const Point &b)const {     return Point(x+b.x,y+b.y);}
    Point operator -(const Point &b)const {     return Point(x-b.x,y-b.y);}
    Point operator *(double a)            {     return Point(x*a,y*a);    }
    Point operator /(double a)            {     return Point(x/a,y/a);    }
    double polar(){  return atan2(y,x);  }//向量的極角   //返回與x軸正向夾角(-pi~pi]
};
inline double cross(Point a,Point b)    {   return a.x*b.y-a.y*b.x;                             } //叉積
#define ll long long
const int maxn=1e3+10;
const double eps=1e-12;
Point a[maxn];
Point b[maxn];
int s[maxn];
int n;
ll ans=0;
bool cmp1(Point a, Point b)//先按象限排序,再按極角排序,再按遠近排序
{
    if (a.y == 0 && b.y == 0 && a.x*b.x <= 0)return a.x>b.x;
    if (a.y == 0 && a.x >= 0 && b.y != 0)return true;
    if (b.y == 0 && b.x >= 0 && a.y != 0)return false;
    if (b.y*a.y <= 0)return a.y>b.y;
    Point one;
    one.y = one.x = 0;
    return cross(one-a,one-b) > 0 || (cross(one-a,one-b) == 0 && a.x < b.x);
}
void slove(int x){
    for(int i=1;i<=n;i++) { b[i]=a[i]; if(i==x) swap(b[i],b[1]); }
    for(int i=2;i<=n;i++)
    {
        b[i]=b[i]-a[x];
        if(fabs(b[i].x)<eps)  b[i].x=fabs(b[i].x);
        if(fabs(b[i].y)<eps)  b[i].y=fabs(b[i].y);
    }
    for(int i=1;i<=n;i++) { b[i].t= b[i].polar();                }
    sort(b+2,b+1+n,cmp1);
    int c=n;
    while(c>1 && b[c].y<=0 )   c--;
    memset(s,0,sizeof(s));
    int temp=0;
    int j=c;
    for(int i=n;i>c;i--){
        while(j>1 && (b[i]^b[j])<0 ) {  j--; temp++; }
        s[i]=s[i+1]+temp;
    }
    j=c+1;
    for(int i=2;i<=c;i++){
        while(j<=n && (b[i]^b[j])>0 ) { j++; }
        int num=j;
        while(j<=n && (b[i]^b[j])>=0) { j++; }
        ans+=(n-j+1)*(num-c-1)+s[j];
        j=num;
    }
}
int main(){  //printf("%.10f",atan2(0.0000000000,-1000000000.0) );
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lf %lf",&a[i].x,&a[i].y);
    for(int i=1;i<=n;i++) { slove(i); }
    printf("%lld\n",ans);
}
View Code

G

思路:棧模擬。

代碼:

#include<bits/stdc++.h>
using namespace std;
int main(){
    string ss; cin>>ss;
    int ans=0;
    stack<char> st;
    for(int i=0;i<ss.size();i++){
        if(st.size()<=1){
            st.push(ss[i]);
        }
        else {
            char x=ss[i];
            char y=st.top(); st.pop();
            char z=st.top(); st.pop();
            if(x==y && y==z){
                ans++;
            }
            else {
                st.push(z);
                st.push(y);
                st.push(x);
            }
        }
    }
    cout<<ans<<endl;
}
View Code

H

I

思路:dfs序+掃描線

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/
 
            const int maxn = 3e5+9;
 
            int le[maxn],ri[maxn];
            vector<int>mp[maxn];
            int id[maxn], dfn[maxn], tim = 0, sz[maxn];
            void dfs(int u) {
                dfn[u] = ++tim;
                id[tim] = u;
                sz[u] = 1;
                for(int v : mp[u]) {
                    dfs(v);
                    sz[u] += sz[v];
                }
            }
            struct node{
                int le, ri, id, op;
                node(int Le, int Ri, int Id, int Op){
                    le = Le; ri = Ri; id = Id; op = Op;
                }
            };
            vector<node> g[maxn];
            ll ans[maxn];
            struct TT{
                ll sum[maxn<<2], lazy[maxn<<2];
                void pushdown(int le, int ri, int rt) {
                    lazy[rt<<1] += lazy[rt];
                    lazy[rt<<1|1] += lazy[rt];
                    int mid = (le + ri) >> 1;
                    sum[rt<<1] += 1ll*lazy[rt] * (mid - le + 1);
                    sum[rt<<1|1] += 1ll*lazy[rt] * (ri - mid);
                    lazy[rt] = 0;
                }
                void update(int L, int R, int c, int le, int ri, int rt) {
                    if(le >= L && ri <= R) {
                        sum[rt] += 1ll * c * (ri - le + 1);
                        lazy[rt] += 1ll * c;
                        return ;
                    }
                    int mid = (le + ri) >> 1;
                    if(lazy[rt]) pushdown(le , ri, rt);
                    if(L <= mid) update(L, R, c, le, mid, rt<<1);
                    if(mid < R) update(L, R, c, mid+1, ri, rt<<1|1);
                    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
                }
                ll query(int L, int R, int le, int ri, int rt) {
                    if(le >= L && ri <= R) {
                        return sum[rt];
                    }
                    int mid = (le + ri) >> 1;
                    if(lazy[rt]) pushdown(le, ri, rt);
                    ll res = 0;
                    if(L <= mid) res += query(L, R, le, mid, rt<<1);
                    if(mid < R) res += query(L, R, mid+1, ri,rt<<1|1);
                    return res;
                }
            } tree;
int main(){
            int n,m;
            scanf("%d%d", &n, &m);
            le[1] = 1, ri[1] = n;
            for(int i=1; i<=m; i++) {
                int u,v,l,r;
                scanf("%d%d%d%d", &u, &v, &l, &r);
                mp[u].pb(v);
                le[v] = l, ri[v] = r;
            }
            int N = m + 1;
            dfs(1);
 
            int q;  scanf("%d", &q);
            for(int i=1; i<=q; i++) {
                int u, le, ri;
                scanf("%d%d%d", &u, &le, &ri);
                int t1 = dfn[u] - 1;
                g[t1].pb(node(le, ri, i, -1));
                g[t1 + sz[u]].pb(node{le, ri, i, 1});
            }
 
            for(int i=1; i<=tim; i++) {
                int u = id[i];
                tree.update(le[u], ri[u], 1, 1, n, 1);
                for(node a : g[i]) {
                    ans[a.id] += 1ll * a.op * tree.query(a.le, a.ri, 1, n, 1);
                }
            }
 
            for(int i=1; i<=q; i++) printf("%lld\n", ans[i]);
            return 0;
}
View Code

J

隊友補了

2019牛客暑期多校訓練營(第九場)

題號 標題 團隊的狀態
A The power of Fibonacci 未通過
B Quadratic equation  通過
C Inversions of all permutations 未通過
D Knapsack Cryptosystem  通過
E All men are brothers  通過
F Birthday Reminders 未通過
G Checkers 未通過
H Cutting Bamboos  通過
I KM and M 未通過
J Symmetrical Painting  通過

A

B

思路:二次剩余

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int p=1e9+7;
int quick(int x,int n,int mod){
    int ans=1;
    while(n){
        if(n&1) ans=1ll*ans*x%mod;
        x=1ll*x*x%mod;
        n=n/2;
    } return ans;
}
int judge(int n,int p) {// p==2 直接 是n    // x*x=n (mod p); (p是奇素數)
    int k=quick(n,(p-1)/2,p);
    if(k==0){  return 0;  } // n==0;  YES;
    if(k==1){  return 1;  } // 1   ;  YES;
    return -1;              // -1  ;  NO;
}
ll w;
struct node{ ll x,y; };
node mul(node a,node b,ll p) {
    node ans={0,0};
    ans.x=((a.x*b.x%p+a.y*b.y%p*w%p)%p+p)%p;
    ans.y=((a.x*b.y%p+a.y*b.x%p)%p+p)%p;
    return ans;
}
ll powwi(node a,ll b,ll p){  // pow
    node ans={1,0};
    while(b){
        if(b&1)ans=mul(ans,a,p);
        a=mul(a,a,p);
        b>>=1;
    }
    return ans.x%p;
}
ll slove(ll n,ll p){
    n%=p; ll a;
    while(1){
        a=rand()%p;
        w=((a*a%p-n)%p+p)%p;
        if(quick(w,(p-1)/2,p)==p-1)break;
    }
    node x={a,1};
    return powwi(x,(p+1)/2,p);
}
int main(){
    int T; scanf("%d",&T);
    while(T--){
        ll b,c; scanf("%lld %lld",&b,&c);
        int x=((1ll*b*b-4*c)%p+p)%p;
        int flag=judge(x,p);
        ll aa,bb;
        if(flag==-1){
            printf("-1 -1\n"); continue;
        }
        else if(flag==0){
            aa=0; bb=p;
        }
        else {
            int cc=slove(x,p);
            aa=min(cc,p-cc);
            bb=max(cc,p-cc);
        }
        if( (b+aa)%2==1 && (b+bb)%2==1) { printf("-1 -1\n"); continue; }
        if( (b+aa)%2==0){
            int x=(b+aa)/2;x=(x%p+p)%p;
            int xx=min(1ll*x,((b-x)%p+p)%p);
            int yy=max(1ll*x,((b-x)%p+p)%p);
            printf("%d %d\n",xx,yy);
        }
        else {
            int x=(b+bb)/2;  x=(x%p+p)%p;
            int xx=min(1ll*x,((b-x)%p+p)%p);
            int yy=max(1ll*x,((b-x)%p+p)%p);
            printf("%d %d\n",xx,yy);
        }
 
    }
}
View Code

C

D

思路:折半枚舉

代碼:

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const int maxn=100;
map<ll,int> mp;
ll a[maxn];
int main(){
    int n; scanf("%d",&n); ll  s; scanf("%lld",&s);
    for(int i=0;i<n;i++) scanf("%lld",&a[i]);
 
    if(n==1){
        if(a[0]==s) printf("1");
        else        printf("0");
            return 0;
    }
    int x=n/2;
    int y=n-x;
    int up=(1<<x);
    for(int i=0;i<up;i++){
        ll temp=0;
        for(int j=0;j<x;j++){
            if(i&(1<<j)){ temp+=a[j]; }
        }
        mp[temp]=i;
    }
    up=(1<<y);
    int ansx=0;
    int ansy=0;
    for(int i=0;i<up;i++){
        ll temp=0;
        for(int j=0;j<y;j++){
            if(i&(1<<j)){ temp+=a[j+x]; }
        }
        if(temp<=s && mp.find(s-temp)!=mp.end()){
            ansx=mp[s-temp];
            ansy=i;
            break;
        }
    }
  //  cout<<ansx<<" "<<ansy<<endl;
    for(int i=0;i<x;i++){
        if(ansx&(1ll<<i)){
            printf("1");
        }else {
            printf("0");
        }
    }
    for(int i=0;i<y;i++){
        if(ansy&(1ll<<i)){
            printf("1");
        }else {
            printf("0");
        }
    }
}
View Code

E

思路:考慮每加一條邊對答案的貢獻。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
int fa[N], n, m, x, y;
LL sz[N];
int Find(int x) {
    if(x == fa[x]) return x;
    else return fa[x] = Find(fa[x]);
}
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) fa[i] = i, sz[i] = 1;
    LL d[4] = {n, n-1, n-2, n-3};
    LL ans = 1;
    for (int i = 0; i < 4; ++i) if(d[i]%2 == 0) {d[i] /= 2; break;}
    for (int i = 0; i < 4; ++i) if(d[i]%2 == 0) {d[i] /= 2; break;}
    for (int i = 0; i < 4; ++i) if(d[i]%2 == 0) {d[i] /= 2; break;}
    for (int i = 0; i < 4; ++i) if(d[i]%3 == 0) {d[i] /= 3; break;}
    for (int i = 0; i < 4; ++i) ans = ans*d[i];
    LL sum = n*1LL*(n-1)/2;
    for (int i = 1; i <= m; ++i) {
        printf("%lld\n", ans);
        scanf("%d %d", &x, &y);
        x = Find(x);
        y = Find(y);
        if(x == y) continue;
        sum -= sz[x]*1LL*(n-sz[x]);
        sum -= sz[y]*1LL*(n-sz[y]);
        sum += sz[x]*1LL*sz[y];
        ans -= sz[x]*1LL*sz[y]*sum;
        sz[y] += sz[x];
        sum += sz[y]*1LL*(n-sz[y]);
        fa[x] = y;
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

F

G

H

思路:二分+主席樹

代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-14 21:32:30
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-15 00:03:11
*/
// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/
 
            const int N = 2e5 + 5, M = 4e6 + 5;//M為節點個數,為Q*log(N)
            int root[N], lson[M], rson[M], value[M], tot = 0;
            ll sum[M];
            const double eps = 1e-7;
            //建樹
            void build(int &x, int l, int r) {
                x = ++tot;
                value[x] = 0;
                sum[x] = 0;
                if(l == r) {
                    return ;
                }
                int m = (l+r) >> 1;
                build(lson[x], l, m);
                build(rson[x], m+1, r);
                value[x] = value[lson[x]] + value[rson[x]];
            }
            // 將某個歷史版本p位置的值加v
            void update(int old, int &x, int p, int v, int l, int r) {
                x = ++tot;
                lson[x] = lson[old], rson[x] = rson[old], value[x] = value[old] + v, sum[x] = sum[old] + p;
                if(l == r) return ;
                int m = (l+r) >> 1;
                if(p <= m) update(lson[x], lson[x], p, v, l, m);
                else update(rson[x], rson[x], p, v, m+1, r);
            }
            //訪問某個歷史版本L到R的區間和
            int query(int L, int R, int x, int l, int r) {
                if(L <= l && r <= R) return value[x];
                int m = (l+r) >> 1, ans = 0;
                if(L <= m) ans += query(L, R, lson[x], l, m);
                if(R > m) ans += query(L, R, rson[x], m+1, r);
                return ans;
            }
            ll query2(int L, int R, int x, int l, int r) {
                if(L <= l && r <= R) return sum[x];
                int m = (l+r) >> 1;
                ll ans = 0;
                if(L <= m) ans += query2(L, R, lson[x], l, m);
                if(R > m) ans += query2(L, R, rson[x], m+1, r);
                return ans;
            }
            const int maxn = 2e5+9;
            ll pre[maxn], a[maxn];
            double cal(double val, int L, int R) {
                int hi = floor(val);
                int cnt = query(0, hi, root[R], 0, 100000) - query(0, hi, root[L-1], 0, 100000);
                double ss =  (R - L + 1 - cnt) * val;
                ss += 1.0*query2(0, hi,root[R], 0, 100000) - query2(0, hi, root[L-1], 0, 100000);
                return ss;
            }
int main(){
            int n,m;
            scanf("%d%d", &n, &m);
            build(root[0], 0, 100000);
            for(int i=1; i<=n; i++) {
                scanf("%lld", &a[i]), pre[i] = pre[i-1] + a[i];
                update(root[i-1], root[i], a[i], 1, 0, 100000);
            }
            while(m--) {
                int L, R, x, y;
                scanf("%d%d%d%d", &L, &R, &x, &y);
                ll ss = pre[R] - pre[L-1];
                double nd = ss*1.0 / y *(y - x);
                double le = 0, ri = 1000000005, res = 0;
                //debug(nd);
                while(le + eps < ri) {
                    double mid = (le + ri) / 2;
                    if(cal(mid, L, R) <= nd) le = mid, res = mid;
                    else ri = mid;
                }
                printf("%.10f\n", res);
            }
            return 0;
}
View Code

I

J

思路:差分

代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-16 15:34:14
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-16 15:41:12
*/
 
// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
            const int maxn = 300009;
            pii a[maxn * 3];
 
int main(){
            int n; 
            scanf("%d", &n);
            int tot = 0;
            for(int i=1; i<=n; i++) {
                int le,ri;
                scanf("%d%d", &le, &ri);
                a[++tot] = pii(2*le, 1);
                a[++tot] = pii(le + ri, -2);
                a[++tot] = pii(2*ri, 1);
            }
            sort(a+1, a+1+tot);
            ll ans = 0, sum = 0;
            ll cnt = a[1].se;
            for(int i=2; i<=tot; i++) {
                sum += cnt * (a[i].fi - a[i-1].fi);
                ans = max(ans, sum);
                cnt += a[i].se;
            }
            printf("%lld\n", ans);
            return 0;
}
View Code

2019牛客暑期多校訓練營(第十場)

題號 標題 團隊的狀態
A Blackjack  通過
B Coffee Chicken  通過
C Gifted Composer 未通過
D Han Xin and His Troops  通過
E Hilbert Sort  通過
F Popping Balloons  通過
G Road Construction  通過
H Stammering Chemists  通過
I Travel Dream 未通過
J Wood Processing  通過

A

隊友補了

B

思路:遞歸

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
LL f[100] = {0, 6, 7}; //57
LL up = 2e12;
int T, n;
string s = "0COFFEE";
string t = "0CHICKEN";
LL k;
void dfs(int x, LL L, LL R) {
    if(R > f[x]) R = f[x];
    if(L > R) return ;
    if(x == 1) {
        for (int i = L; i <= R; ++i) putchar(s[i]);
    }
    else if(x == 2) {
        for (int i = L; i <= R; ++i) putchar(t[i]);
    }
    else {
        if(L > f[x-2]) {
            dfs(x-1, L-f[x-2], R-f[x-2]);
        }
        else if(R > f[x-2]) {
            dfs(x-2, L, f[x-2]);
            dfs(x-1, 1, R-f[x-2]);
        }
        else {
            dfs(x-2, L, R);
        }
    }
}
int main() {
    for (int i = 3; i < 100; ++i) {
        f[i] = f[i-1]+f[i-2];
        if(f[i] > up) break;
    }
    scanf("%d", &T);
    while(T--) {
        scanf("%d %lld", &n, &k);
        if(n%2) dfs(min(57, n), k, k+9);
        else dfs(min(56, n), k, k+9);
        puts("");
    }
    return 0;
}
View Code

C

D

思路:大數寫擴展中國剩余定理

代碼:

import java.math.BigInteger;
import java.util.*;
 
public class Main {
 
    /**
     * @param args
     */
    static BigInteger x;
    static BigInteger y;
    public static BigInteger exgcd(BigInteger a, BigInteger b) {
        if(b.compareTo(BigInteger.ZERO) == 0){
            x = BigInteger.ONE;
            y = BigInteger.ZERO;
            return a;
        }
        BigInteger gcd = exgcd(b, a.remainder(b));
        BigInteger t = x;
        x = y;
        y = t.subtract(a.divide(b).multiply(y));
        return gcd;
    }
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        int a[] = new int[105];
        int b[] = new int[105];
        int n = reader.nextInt();
        BigInteger m = reader.nextBigInteger();
        for (int i = 1; i <= n; ++i) {
            b[i] = reader.nextInt();
            a[i] = reader.nextInt();
        }
        BigInteger M = BigInteger.valueOf(b[1]), ans = BigInteger.valueOf(a[1]);
        boolean f = true;
        for (int i = 2; i <= n; ++i) {
            BigInteger A = M, B = BigInteger.valueOf(b[i]), C = (BigInteger.valueOf(a[i]).subtract(ans)).remainder(B);
            C = C.add(B).remainder(B);
            BigInteger gcd = exgcd(A, B), bg = B.divide(gcd);
            if(C.remainder(gcd).compareTo(BigInteger.ZERO) != 0) {
                f = false;
                break;
            }
            x = (x.multiply(C.divide(gcd))).remainder(bg);
            ans = ans.add(x.multiply(M));
            M = M.multiply(bg);
            ans = ans.remainder(M);
        }
        ans = (ans.remainder(M).add(M)).remainder(M);
        if(f == false) System.out.println("he was definitely lying");
        else if(ans.compareTo(m) > 0) System.out.println("he was probably lying");
        else System.out.println(ans);
    }
 
}
View Code

E

思路:遞歸

代碼:

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/
            const int maxn = 1e6+9;
            pii a[maxn];
            ll ksm(ll a, ll b) {
                ll res = 1;
                while(b > 0) {
                    if(b & 1) res = res * a;
                    a = a * a;
                    b >>= 1;
                }
                return res;
            }
            vector<pii>ans;
            void dfs(int pt, int inv ,vector<pii>vec, int k, int xbase, int ybase){
                if(vec.size() == 0) return;
                if(vec.size() == 1) {
                    for(pii p : vec) ans.pb(p);
                    return;
                }
                if(k == 0){
                    for(pii p : vec) ans.pb(p);
                    return;
                }
                vector<pii>v[5];
                int mid = ksm(2 , k-1);
                for(pii t : vec) {
                    int x = t.fi, y = t.se;
                    x -= xbase, y -= ybase;
                    if(x <= mid && y <= mid) v[1].pb(t);
                    else if(x > mid && y <= mid) v[2].pb(t);
                    else if(x > mid && y > mid)  v[3].pb(t);
                    else v[4].pb(t);
                }
 
                if(pt == 1) {
                    if(inv){
                        dfs(4, inv ^ 1, v[4], k-1, xbase, ybase + mid);
                        dfs(1, inv, v[3], k-1, xbase+mid, ybase + mid);
                        dfs(1, inv, v[2], k-1, xbase+mid, ybase);
                        dfs(2, inv ^ 1, v[1], k-1,xbase, ybase);
                    }
                    else {
                        dfs(2, inv ^ 1, v[1], k-1,xbase, ybase);
                        dfs(1, inv, v[2], k-1,xbase+mid, ybase);
                        dfs(1, inv, v[3], k-1,xbase+mid, ybase + mid);
                        dfs(4, inv ^ 1, v[4], k-1, xbase, ybase + mid);
                    }
                }
                else if(pt == 2){
                    if(inv) {
                        dfs(1, inv ^ 1, v[1], k-1,xbase, ybase);
                        dfs(2, inv, v[4], k-1, xbase, ybase + mid);
                        dfs(2, inv, v[3], k-1,xbase+mid, ybase + mid);
                        dfs(3, inv ^ 1, v[2], k-1,xbase+mid, ybase);
                    }
                    else {
                        dfs(3, inv ^ 1, v[2], k-1,xbase+mid, ybase);
                        dfs(2, inv, v[3], k-1,xbase+mid, ybase + mid);
                        dfs(2, inv, v[4], k-1, xbase, ybase + mid);
                        dfs(1, inv ^ 1, v[1], k-1,xbase, ybase);
                    }
                }
                else if(pt == 3) {
                    if(inv) {
                        dfs(2, inv ^ 1, v[2], k-1,xbase+mid, ybase);
                        dfs(3, inv, v[1], k-1,xbase, ybase);
                        dfs(3, inv, v[4], k-1,xbase, ybase + mid);
                        dfs(4, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid);
                    }
                    else {
                        dfs(4, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid);
                        dfs(3, inv, v[4], k-1, xbase, ybase + mid);
                        dfs(3, inv, v[1], k-1,xbase, ybase);
                        dfs(2, inv ^ 1, v[2], k-1,xbase+mid, ybase);
                    }
                }
                else {
                    if(inv) {
                        dfs(3, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid);
                        dfs(4, inv, v[2], k-1,xbase+mid, ybase);
                        dfs(4, inv, v[1], k-1,xbase, ybase);
                        dfs(1, inv ^ 1, v[4], k-1, xbase, ybase + mid);
                    }
                    else {
                        dfs(1, inv ^ 1, v[4], k-1, xbase, ybase + mid);
                        dfs(4, inv, v[1], k-1,xbase, ybase);
                        dfs(4, inv, v[2], k-1,xbase+mid, ybase);
                        dfs(3, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid);
                    }
                }
            }
int main(){
            int n, k;
            scanf("%d%d", &n, &k);
            vector<pii>in;
            for(int i=1; i<=n; i++) {
                int x,y;
                scanf("%d%d", &x, &y);
                in.pb(pii(x, y));
            }
            dfs(1, 0, in, k, 0, 0);
            for(pii p : ans) {
                printf("%d %d\n", p.fi, p.se);
            }
            return 0;
}
View Code

F

思路:暴力+multiset

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 1;
multiset<int> s;
vector<int> vc[N];
int n, x, y, r, cnt[N], tot[N];
int main() {
    scanf("%d %d", &n, &r);
    for (int i = 1; i <= n; ++i) {
        scanf("%d %d", &x, &y);
        vc[x].pb(y);
        cnt[y]++;
    }
    for (int i = 0; i < N; ++i) {
        tot[i] = cnt[i];
        if(i+r < N) tot[i] += cnt[i+r];
        if(i+r+r < N) tot[i] += cnt[i+r+r];
        s.insert(tot[i]);
    }
    int ans = 0;
    for (int x = 0; x < N; ++x) {
        int tmp = vc[x].size();
        if(x+r < N) tmp += vc[x+r].size();
        if(x+r+r < N) tmp += vc[x+r+r].size();
        for (int y : vc[x]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r]--;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y]--;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r-r]--;
            }
        }
        if(x+r < N)
        for (int y : vc[x+r]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r]--;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y]--;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r-r]--;
            }
        }
        if(x+r+r < N)
        for (int y : vc[x+r+r]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r]--;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y]--;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r-r]--;
            }
        }
        tmp += *s.rbegin();
        ans = max(ans, tmp);
        for (int y : vc[x]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r]++;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y]++;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r-r]++;
            }
        }
        if(x+r < N)
        for (int y : vc[x+r]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r]++;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y]++;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r-r]++;
            }
        }
        if(x+r+r < N)
        for (int y : vc[x+r+r]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r]++;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y]++;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r-r]++;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}
View Code

G

思路:對稱軸一定平行或垂直與任意兩點連線。

代碼:

#include<bits/stdc++.h>
using namespace std;
#define pb emplace_back
const double eps=1e-6;
const int maxn=310;
struct Point{
    double x,y;
    double w;
    Point(){ x=0,y=0; }
    Point(double _x,double _y):x(_x),y(_y){}
};
int n;
Point pa[maxn];
bool up(Point a,Point b){
    return a.w<b.w;
}
bool upx(Point a,Point b){
    return a.x<b.x;
}
bool upy(Point a,Point b){
    return a.y<b.y;
}
double k[maxn*maxn*2];
inline double dis(double b, double k) {
    return b/sqrt(k*k+1.0);
}
inline double solve(double l, double r, double k) {
    return dis(r-l, k)/2.0;
}
int main(){
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> pa[i].x >> pa[i].y;
    int tot=0;
    double ans=0;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            if(fabs(pa[i].x-pa[j].x) < eps) continue;
            else if(fabs(pa[i].y-pa[j].y) < eps) continue;
            else {
                k[++tot]=(pa[j].y-pa[i].y)/(pa[j].x-pa[i].x);
                k[++tot] = -(pa[j].x-pa[i].x)/(pa[j].y-pa[i].y);
            }
        }
    }
    sort(pa+1,pa+1+n,upx);
    ans=max((pa[n/2+1].x-pa[n/2].x)/2,ans);
    sort(pa+1,pa+1+n,upy);
    ans=max((pa[n/2+1].y-pa[n/2].y)/2,ans);
    for (int i = 1; i <= tot; ++i) {
        for (int j = 1; j <= n; ++j) pa[j].w = pa[j].y-k[i]*pa[j].x;
        sort(pa+1, pa+1+n, up);
        ans = max(ans, solve(pa[n/2].w, pa[n/2+1].w, k[i]));
    }
    cout << fixed << setprecision(12) << ans <<endl;
    return 0;
}
View Code

H

思路:水題

代碼:

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/
 
            int du[7], cnt[7];
            pii a[7];
 
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                for(int i=1; i<=6; i++) du[i] = 0, cnt[i] = 0;
 
                for(int i=1; i<=5; i++) {
                    int u,v;
                    scanf("%d%d", &u, &v);
                    du[u] ++; du[v]++;
                    a[i].fi = u, a[i].se = v;
                }
                for(int i=1; i<=6; i++) cnt[du[i]]++;
                if(cnt[2] == 4) puts("n-hexane");
                else if(cnt[4] == 1) puts("2,2-dimethylbutane");
                else if(cnt[3] == 2) puts("2,3-dimethylbutane");
                else {
                    int cc1 = 0;
                    for(int i=1; i<=5; i++) {
                        int u = a[i].fi, v = a[i].se;
                        if(du[u] == 3 && du[v] == 1) cc1++;
                        if(du[v] == 3 && du[u] == 1) cc1++;
                    }
                    if(cc1 == 1) puts("3-methylpentane");
                    else puts("2-methylpentane");
                }
            }
            return 0;
}
View Code

I

J

思路:斜率優化dp,維護遞增斜率$\frac{dp[j]-dp[k]+sum[k]-sum[j]+h[j+1]*sw[j]-h[k+1]*sw[k]}{h[j+1]-h[k+1]}$,其中$sum$是按高度排序后面積的前綴和,$sw$是寬度前綴和。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 5e3 + 10, M = 2e3 + 5;
LL sum[N], sw[N], dp[M][N];
int h[N], w[N];
pii a[N];
int n, k;
deque<int> q[M];
LL up(int p, int k, int j) {
    return dp[p][j]-dp[p][k]+sum[k]-sum[j]+h[j+1]*sw[j]-h[k+1]*sw[k];
}
LL dw(int k, int j) {
    return h[j+1]-h[k+1];
}
bool g(int p, int k, int j, LL C) {
    return up(p, k, j) <= C*1.0*dw(k, j);
}
bool gg(int p, int k, int j, int i) {
    return up(p, k, j)*1.0*dw(j, i) >= up(p, j, i)*1.0*dw(k, j);
}
int main() {
    scanf("%d %d", &n, &k);
    for (int i = 1; i <= n; ++i) scanf("%d %d", &a[i].se, &a[i].fi);
    sort(a+1, a+1+n);
    for (int i = 1; i <= n; ++i) h[i] = a[i].fi, w[i] = a[i].se, sw[i] = sw[i-1]+w[i], sum[i] = sum[i-1] + w[i]*1LL*h[i];
    q[0].push_back(0);
    for (int i = 1; i <= n; ++i) {
        for (int j = min(k, i); j >= 1; --j) {
            while(q[j-1].size() >= 2) {
                int a = q[j-1].front();
                q[j-1].pop_front();
                int b = q[j-1].front();
                if(g(j-1, a, b, sw[i])) ;
                else {
                    q[j-1].push_front(a);
                    break;
                }
            }
            if(!q[j-1].empty()) {
                int x = q[j-1].front();
                dp[j][i] = dp[j-1][x] + sum[i]-sum[x]-h[x+1]*(sw[i]-sw[x]);
                 while(q[j].size() >= 2) {
                    int b = q[j].back();
                    q[j].pop_back();
                    int a = q[j].back();
                    if(gg(j, a, b, i)) ;
                    else {
                        q[j].push_back(b);
                        break;
                    }
                }
                q[j].push_back(i);
            }
        }
    }
    printf("%lld\n", dp[k][n]);
    return 0;
}
View Code

杭電

2019 Multi-University Training Contest 1

Solved Pro.ID Title
   1001 Blank
  1002 Operation
   1003 Milk
  1004 Vacation
  1005 Path
  1006 Typewriter
  1007 Meteor
  1008 Desert
  1009 String
  1010 Kingdom
   1011 Function
   1012 Sequence
  1013 Code

1001

思路:dp

$dp[i][j][k][l]$表示每種顏色出現位置分別為$i$,$j$,$k$,$l$,$i \le j \le k \le l$,其中,等號只有在等於0時才取得到。

不必在意每種顏色在哪個位置,只需要知道這四個位置的顏色都是不同的。然后考慮轉移到,有如下四種狀態可以轉移到:

$dp[j][k][l][l+1]$,$dp[i][k][l][l+1]$,$dp[i][j][l][l+1]$,$dp[i][j][k][l+1]$,然后第四個維度滾動數組優化一下

於是時間復雜度$O(C(n, 4))$,空間復雜度$O(n^3)$

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 103;
const int MOD = 998244353;
int dp[N][N][N][2], n, m, l, r, x, T;
vector<int> vc[N][5];
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; ++i) for (int j = 1; j <= 4; ++j) vc[i][j].clear();
        for (int i = 1; i <= m; ++i) scanf("%d %d %d", &l, &r, &x), vc[r][x].pb(l);
        dp[0][0][0][0] = 1;
        int now = 0, ans = 0;
        for (int l = 0; l <= n; ++l) {
            now ^= 1;
            for (int i = 0; i <= l+1; ++i) for (int j = i; j <= l+1; ++j) for (int k = j; k <= l+1; ++k) dp[i][j][k][now] = 0;
            for (int k = l; k >= 0; --k) {
                bool f = false;
                for (int x : vc[l][1]) {
                    if(x <= k) {
                        f = true;
                        break;
                    }
                }
                if(f) continue;
                f = false;
                for (int x : vc[l][2]) {
                    if(x > k) {
                        f = true;
                        break;
                    }
                }
                if(f) break;
                for (int j = k; j >= 0; --j) {
                    bool f = false;
                    for (int x : vc[l][2]) {
                        if(x <= j) {
                            f = true;
                            break;
                        }
                    }
                    if(f) continue;
                    f = false;
                    for (int x : vc[l][3]) {
                        if(x > j) {
                            f = true;
                            break;
                        }
                    }
                    if(f) break;
                    for (int i = j; i >= 0; --i) {
                        bool f = false;
                        for (int x : vc[l][3]) {
                            if(x <= i) {
                                f = true;
                                break;
                            }
                        }
                        if(f) continue;
                        f = false;
                        for (int x : vc[l][4]) {
                            if(x > i) {
                                f = true;
                                break;
                            }
                        }
                        if(f) break;
                        //cout << i << " " << j << " " << k << " " << l << endl;
                        if(l != n) {
                            (dp[j][k][l][now] += dp[i][j][k][now^1]) %= MOD;
                            (dp[i][k][l][now] += dp[i][j][k][now^1]) %= MOD;
                            (dp[i][j][l][now] += dp[i][j][k][now^1]) %= MOD;
                            (dp[i][j][k][now] += dp[i][j][k][now^1]) %= MOD;
                        }
                        else {
                            (ans += dp[i][j][k][now^1]) %= MOD;
                        }
                    }
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

1002

思路:線性基+貪心,cf原題,詳見FCY博客

代碼:

using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e6 + 3;
int a[N], base[N][30], pos[N][30];
inline void add(int p) {
    int x = a[p];
    int pp = p;
    for (int i = 29; i >= 0; --i) base[p][i] = base[p-1][i], pos[p][i] = pos[p-1][i];
    for (int i = 29; i >= 0; --i) {
        if(x&(1<<i)) {
            if(!base[pp][i]) {
                base[pp][i] = x;
                pos[pp][i] = p;
                return ;
            }
            if(p > pos[pp][i]) swap(base[pp][i], x), swap(pos[pp][i], p);
            x ^= base[pp][i];
        }
    }
}
inline int solve(int L, int R) {
    int res = 0;
    for (int i = 29; i >= 0; --i) {
        if(base[R][i] && pos[R][i] >= L) {

            if((base[R][i]^res) > res) res ^= base[R][i];
        }
    }
    return res;
}
int T, n, m, op, l, r;
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), add(i);
        int ans = 0;
        for (int i = 1; i <= m; ++i) {
            scanf("%d", &op);
            if(op == 0) {
                scanf("%d %d", &l, &r);
                l = (l^ans)%n+1;
                r = (r^ans)%n+1;
                if(l > r) swap(l, r);
                ans = solve(l, r);
                printf("%d\n", ans);
            }
            else {
                scanf("%d", &l);
                l ^= ans;
                a[++n] = l;
                add(n);
            }
        }
    }
    return 0;
}
/*
8
8 8
1 2 3 4 5 6 7 8
*/
View Code  

1003

1004

思路:貪心,假設每輛車都跑到最前面,時間取最大值

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 3;
int l[N];
int s[N];
int v[N];
LL  ll[N];

int main(){
    int n;
    while(~scanf("%d",&n)){
        for(int i=0;i<=n;i++) scanf("%d",&l[i]);
        for(int i=0;i<=n;i++) scanf("%d",&s[i]);
        for(int i=0;i<=n;i++) scanf("%d",&v[i]);
        for(int i=1;i<=n;i++){
            ll[i]=ll[i-1]+l[i];
        }
        double ans=0;
        for(int i=n;i>=0;i--){
            ans=max(ans,(ll[i]+s[i])*1.0/v[i]);
        }
        printf("%.10f\n",ans);
    }
}
View Code

1005

思路:先建出從1出發的dijkstra圖,然后在這張圖上跑1到n的最小割。

代碼:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;


template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

/**********showtime************/
            const int maxn = 10009;
            vector<pii>mp[maxn];
            ll dis[maxn];
                int n,m;
            void dji(int s) {
                priority_queue<pll>que;
                que.push(pll(0, s));
                for(int i=1; i<=n; i++) {
                    dis[i] = inff;
                }
                dis[s] = 0;
                while(!que.empty()) {
                    pll t = que.top(); que.pop();
                    int u = t.se;
                    if(dis[u] < -1ll*t.fi) continue;
                    for(int i=0; i<mp[u].size(); i++) {
                        int v = mp[u][i].fi;
                        int w = mp[u][i].se;
                        if(dis[v] > dis[u] + w) {
                            dis[v] = dis[u] + w;
                            que.push(pll(-1ll*dis[v], v));
                        }
                    }
                }
            }

            struct E{
                int v;
                ll w;
                int nxt;
            }edge[20009];
            int head[maxn], gtot = 0;
            void addedge(int u, int v, ll w) {
                edge[gtot].v = v;
                edge[gtot].w = w;
                edge[gtot].nxt = head[u];
                head[u] = gtot++;

                edge[gtot].v = u;
                edge[gtot].w = 0;
                edge[gtot].nxt = head[v];
                head[v] = gtot++;
            }

            int dd[maxn], cur[maxn];
            bool bfs(int s, int t) {
                for(int i=s; i<=t; i++) cur[i] = head[i], dd[i] = inf;
                queue<int>que;
                que.push(s);
                dd[s] = 0;
                while(!que.empty()) {
                    int u = que.front();
                    que.pop();
                    for(int i=head[u]; ~i; i=edge[i].nxt) {
                        int v = edge[i].v;ll  w = edge[i].w;
                        if(w > 0 && dd[v] > dd[u] + 1) {
                            dd[v] = dd[u] + 1;
                            que.push(v);
                        }
                    }
                }
                return dd[t] < inf;
            }
            ll dfs(int u, int t, ll maxflow) {
                if(u == t || maxflow == 0) return maxflow;
                for(int i=cur[u]; ~i; i=edge[i].nxt) {
                    cur[u] = i;
                    int v = edge[i].v; ll w = edge[i].w;
                    if(dd[v] == dd[u] + 1 && w > 0) {
                        ll f = dfs(v, t, min(maxflow, 1ll*w));
                        if(f > 0) {
                            edge[i].w -= f;
                            edge[i ^ 1].w += f;
                            return f;
                        }
                    }
                }
                return 0;
            }
            ll dinic(int s, int  t){
                ll flow = 0;
                while(bfs(s, t)) {
                    while(ll f = dfs(s, t, inff)) flow += f;
                }
                return flow;
            }
int main(){
            int T;  scanf("%d", &T);
            while(T--) {

                scanf("%d%d", &n, &m);
                gtot = 0;
                for(int i=1; i<=n; i++) mp[i].clear(), head[i] = -1;
                for(int i=1; i<=m; i++) {
                    int u,v,c;
                    scanf("%d%d%d", &u, &v, &c);
                    mp[u].pb(pii(v, c));
                }
                dji(1);
                for(int i=1; i<=n; i++) {
                    int u = i;
                    for(pii p : mp[i]) {
                        int v = p.fi, w = p.se;
                        if(dis[v] == dis[u] + w){
                            addedge(u, v, w);
                        }
                    }
                }
                printf("%lld\n", dinic(1, n));
            }
            return 0;
}
View Code

1006

隊友補了

1007

1008

1009

思路:貪心,每次在能選的字符中選個最小的。用隊列記錄每個字符的位置,並預處理好每個位置后面每個字符的個數。有很一些限制條件,寫起來不簡單。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
char s[N];
queue<int> q[26];
int L[26], R[26], dp[N][26], n, k;
vector<int> vc;
int main() {
    while(~scanf("%s %d", s+1, &k)) {
        int n = strlen(s+1);
        for (int i = 0; i < 26; ++i) scanf("%d %d", &L[i], &R[i]);
        for (int i = 0; i < 26; ++i) dp[n+1][i] = 0;
        for (int i = n; i >= 1; --i) {
            for (int j = 0; j < 26; ++j) dp[i][j] = dp[i+1][j];
            dp[i][s[i]-'a']++;
        }
        for (int i = 0; i < 26; ++i) while(!q[i].empty()) q[i].pop();
        for (int i = 1; i <= n; ++i) q[s[i]-'a'].push(i);
        vc.clear();
        int tot = 0;
        for (int i = 0; i < 26; ++i) tot += L[i];
        while(true) {
            if(vc.size() == k) break;
            bool f = false;
            for (int i = 0; i < 26; ++i) {
                if(!q[i].empty() && R[i] > 0 && tot-L[i] <= k-vc.size()-1) {
                    //cout << i <<endl;
                    bool ff = false;
                    int CC = 0;
                    for (int j = 0; j < 26; ++j) {
                        if(dp[q[i].front()][j] < L[j]) ff = true;
                        CC += min(R[j], dp[q[i].front()][j]);
                    }
                    if(ff) continue;
                    if(CC < k-vc.size()) continue;
                    vc.pb(q[i].front());
                    q[i].pop();
                    f = true;
                    if(L[i]) {
                        L[i]--;
                        tot--;
                    }
                    if(R[i]) R[i]--;
                    break;
                }
            }
            if(!f) break;
            if(!vc.empty())
            for (int i = 0; i < 26; ++i) {
                while(!q[i].empty() && q[i].front() < vc.back()) q[i].pop();
            }
        }
        if(vc.size() != k) printf("-1\n");
        else {
            for (int x : vc) putchar(s[x]);
            puts("");
        }
    }
    return 0;
}
/*
ababababab 10
5 5
5 5
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
*/
View Code

1010

1011

隊友補了

1012

思路:母函數+NTT

代碼:

#include<bits/stdc++.h>
using namespace std;
#define LL long long

const int N = 400100, P = 998244353;
const int M = 1.2e6;
inline int qpow(int x, int y) {
  int res(1);
  while (y) {
    if (y & 1) res = 1ll * res * x % P;
    x = 1ll * x * x % P;
    y >>= 1;
  }
  return res;
}

int r[N];
void ntt(int *x, int n, int opt) {
  register int i, j, k, m, gn, g, tmp;
  for (i = 0; i < n; ++i)
    if (r[i] < i) swap(x[i], x[r[i]]);
  for (m = 2; m <= n; m <<= 1) {
    k = m >> 1;
    gn = qpow(3, (P - 1) / m);    ///3是原根
    for (i = 0; i < n; i += m) {
      g = 1;
      for (j = 0; j < k; ++j, g = 1ll * g * gn % P) {
        tmp = 1ll * x[i + j + k] * g % P;
        x[i + j + k] = (x[i + j] - tmp + P) % P;
        x[i + j] = (x[i + j] + tmp) % P;
      }
    }
  }
  if (opt == -1) {
    reverse(x + 1, x + n);
    register int inv = qpow(n, P - 2);
    for (i = 0; i < n; ++i) x[i] = 1ll * x[i] * inv % P;
  }
}

int A[N], B[N], C[N], f[M], invf[M], a[N];
int T, nm, q, x, y, z, c;
inline void init() {
    f[0] = 1;
    for (int i = 1; i < M; ++i) f[i] = (f[i-1]*1LL*i)%P;
    invf[M-1] = qpow(f[M-1], P-2);
    for (int i = M-2; i >= 0; --i) invf[i] = invf[i+1]*1LL*(i+1)%P;
}
inline int CC(int n, int m) {
    if(m < 0 || m > n) return 0;
    return (f[n]*1LL*invf[m]%P*1LL*invf[n-m])%P;
}
int main() {
    init();
    scanf("%d", &T);
    while(T--){
        int n, m, L = 0;
        x = y = z = 0;
        scanf("%d %d", &nm, &q);
        for (int i = 0; i < nm; ++i) scanf("%d", &a[i]);
        for (int i = 0; i < q; ++i) {
            scanf("%d", &c);
            if(c == 1) x++;
            else if(c == 2) y++;
            else z++;
        }
        L = 0;
        n = m = nm;
        m = n+m;
        for(n = 1; n <= m; n <<= 1) L++;
        for (int i = 0; i < n; i++) r[i] = (r[i>>1]>>1) | ((i&1) << L-1);
        if(x) {
            for (int i = 0; i < nm; ++i) A[i] = a[i];
            for (int i = 0; i < nm; ++i) B[i] = CC(i+x-1, i);
            ntt(A, n, 1);
            ntt(B, n, 1);
            for (int i = 0; i < n; ++i) C[i] = 1ll * A[i] * B[i] % P;
            ntt(C, n, -1);
            for (int i = 0; i < nm; ++i) a[i] = C[i];
            for (int i = 0; i < n; ++i) A[i] = B[i] = C[i] = 0;
        }
        if(y) {
            for (int i = 0; i < nm; ++i) A[i] = a[i];
            for (int i = 0; 2*i < nm; ++i) B[2*i] = CC(i+y-1, i);
            ntt(A, n, 1);
            ntt(B, n, 1);
            for (int i = 0; i < n; ++i) C[i] = 1ll * A[i] * B[i] % P;
            ntt(C, n, -1);
            for (int i = 0; i < nm; ++i) a[i] = C[i];
            for (int i = 0; i < n; ++i) A[i] = B[i] = C[i] = 0;
        }
        if(z) {
            for (int i = 0; i < nm; ++i) A[i] = a[i];
            for (int i = 0; 3*i < nm; ++i) B[3*i] = CC(i+z-1, i);
            ntt(A, n, 1);
            ntt(B, n, 1);
            for (int i = 0; i < n; ++i) C[i] = 1ll * A[i] * B[i] % P;
            ntt(C, n, -1);
            for (int i = 0; i < nm; ++i) a[i] = C[i];
            for (int i = 0; i < n; ++i) A[i] = B[i] = C[i] = 0;
        }
        LL ans = 0;
        for (int i = 0; i < nm; ++i) ans ^= ((i+1)*1LL*a[i]);
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

1013

思路:假設要求的三個變量為$(b,w1,w2)$。首先很容易想到$b$只是做一個平移運動,只要原來應該大於0的元素的最小值大於應該小於0的元素的最大值,

就一定可以找到一個$b$平移所有元素使得大於0的元素大於0,小於0的小於0。所以$b$完全可以忽略。那么就只有兩個變量$w1$,$w2$需要確定。根據上面

的結論,我們要找到$w1$,$w2$,使得應該大於0的元素的相對大小大於小於0的。即對於任意$i$,$j$,如果$y_i == 1 且 y_j == -1$,那么要保證

$w1*x1_i +w2*x2_i > w1*x1_j +w2*x2_j$ 。兩邊同除以$w1$,$x1_i +\frac{w2}{w1}*x2_i > x1_j +\frac{w2}{w1}*x2_j$ ,所以只要確定一個變量$\frac{w2}{w1}$

就可以啦,於是$n^2$枚舉,判斷這個變量的存不存在一個可行區間就可以啦。如果$w1==0$怎么辦,那么假設它等於0再判斷一遍,我沒有判也過了。

還有一點,由於$w1$的正負性不確定,所以$x1_i$的系數不一定是1,可能還是-1,兩個都要判一遍。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 105;
const double INF = 1LL<<60;
int T, n;
int x1[N], x2[N], y[N];
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d %d %d", &x1[i], &x2[i], &y[i]);
        double L = -(1LL<<60), R =1LL<<60;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                if(i == j) continue;
                if(y[i] == 1 && y[j] == -1) {
                    if(x2[i] == x2[j]) continue;
                    double d = x2[j]-x2[i];
                    double up = x1[i]-x1[j];
                    if(d < 0) L = max(L, up/d);
                    else R = min(R, up/d);
                }
            }
        }
        if(L <= R) {
            printf("Successful!\n");
            continue;
        }

        L = -(1LL<<60), R =1LL<<60;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                if(i == j) continue;
                if(y[i] == 1 && y[j] == -1) {
                    if(x2[i] == x2[j]) continue;
                    double d = x2[j]-x2[i];
                    double up = -x1[i]+x1[j];
                    if(d < 0) L = max(L, up/d);
                    else R = min(R, up/d);
                }
            }
        }
        if(L <= R) {
            printf("Successful!\n");
            continue;
        }
        printf("Infinite loop!\n");
    }
    return 0;
}
View Code

2019 Multi-University Training Contest 2

Solved Pro.ID Title
  1001 Another Chess Problem
  1002 Beauty Of Unimodal Sequence
  1003 Coefficient
  1004 Double Tree
  1005 Everything Is Generated In Equal Probability
  1006 Fantastic Magic Cube
  1007 Game
    1008 Harmonious Army
  1009 I Love Palindrome String
  1010 Just Skip The Problem
  1011 Keen On Everything But Triangle
    1012 Longest Subarray

1001

1002

1003

1004

1005

思路:打表找規律

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int MOD = 998244353;
const int N = 3e3 + 10;
LL t[N], s[N];
LL q_pow(LL n, LL k) {
    LL res = 1;
    while(k) {
        if(k&1) res = (res*n)%MOD;
        n = (n*n)%MOD;
        k >>= 1; 
    }
    return res;
}
int n;
int main() {
    t[1] = 0;
    LL now = 2;
    for (int i = 2; i < N; ++i) {
        t[i] = (t[i-1]+now)%MOD;
        now = (now+2)%MOD;
    }
    for (int i = 1; i < N; ++i) s[i] =(s[i-1]+t[i])%MOD;
    while(~scanf("%d", &n)) {
        printf("%lld\n", s[n]*q_pow(3*n, MOD-2)%MOD);
    }
    return 0;
}
View Code

1006

1007

1008

隊友補了

1009

思路:回文自動機,在回文樹上dfs,跑一個前綴的正反hash值,然后就可以判斷每一個本質不同的回文串的一半是不是也是回文串。

隊友代碼:

#include<bits/stdc++.h>
#define ll long long
#define LL long long
using namespace std;
const int maxn=3e5+10;
const int mod=1e9+7;
const int h1=222333;
char ss[maxn];
int a[maxn];
int ha[maxn];
int hb[maxn];
int hh[maxn];
struct PAM{
    #define ll long long
    #define LL long long
    static const int maxn=3e5+10;
    static const int num=27;
    int fail[maxn],cnt[maxn],len[maxn],ch[maxn][num];
    int last,tot;
    LL ans;
    void inint(){
        last=0;  tot=0;
        fail[0]=fail[1]=1;
        len[0]=0; len[1]=-1; tot++;
    }
    int get_fail(int p,int pos){
         while(ss[pos-len[p]-1]!=ss[pos]) p=fail[p];
         return p;
    }
    void add(int x,int pos){
        int p=get_fail(last,pos);
        if(!ch[p][x]){
            len[++tot]=len[p]+2;
            fail[tot]=ch[get_fail(fail[p],pos)][x];
            ch[p][x]=tot; ans++;
        }
        cnt[last=ch[p][x]]++;
    }
    void count(){  //  bu zhi bu tong hui wen ge shu
        for(int i=tot;i>=0;i--){
            cnt[fail[i]]+=cnt[i];
        }
    }
    void dfs(int x,int pos){
        for(int i=0;i<num;i++){
            if(ch[x][i]){
                if(pos==0) ha[pos]=(1ll*i)%mod;
                else       ha[pos]=(1ll*ha[pos-1]*h1+i)%mod;
                if(pos==0) hb[pos]=(1ll*i*hh[pos])%mod;
                else       hb[pos]=(1ll*i*hh[pos]+hb[pos-1])%mod;
                int k=ch[x][i];
                if(ha[pos]==hb[pos]){
                    a[len[k]]+=cnt[k];
                }
                dfs(k,pos+1);

            }
        }
    }
    void work(){
        dfs(0,0);
        dfs(1,0);
    }
    void clear(){
        for(int i=0;i<=tot;i++){
            fail[i]=0; len[i]=0; cnt[i]=0;
            for(int j=0;j<num;j++) ch[i][j]=0;
        }
        last=tot=ans=0;
    }
}pam;
int main(){
    hh[0]=1;  for(int i=1;i<maxn;i++) hh[i]=1ll*hh[i-1]*h1%mod;
    while(~scanf("%s",ss)){
        int l=strlen(ss); pam.inint();  //cout<<l<<endl;
        for(int i=0;i<l;i++)  pam.add(ss[i]-'a',i);
        pam.count();  pam.work();
        for(int i=1;i<=l;i++){
            if(i!=1) printf(" ");
            printf("%d",a[i]); a[i]=0;
        }printf("\n");
        pam.clear();
    }
}
View Code

1010

思路:$n!$,當$n>=mod$時,等於$0$

代碼:

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;


template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e6+3;

/**********showtime************/
            const int maxn = 1e6+5;
            ll fac[maxn];
int main(){
            int n;
            fac[0] = 1; 
            for(int i=1; i<maxn; i++) {
                fac[i] = fac[i-1] * i % mod;
            }
            while(~scanf("%d", &n)) {
                if(n >= mod) puts("0");
                else {
                    
                    printf("%lld\n", fac[n]);
                }
            }

            return 0;
}
View Code

1011

思路:主席樹找區間第$k$大

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5, M = 5e6 + 5;//M為節點個數,為Q*log(N)
int root[N], lson[M], rson[M], value[M], tot = 0;
int a[N], v[N];
vector<int>vc;
int n, m, l, r, k, q;
void build(int &x, int l, int r) {
    x = ++tot;
    if(l == r) {
        value[x] = 0;
        return ;
    }
    int m = (l+r) >> 1;
    build(lson[x], l, m);
    build(rson[x], m+1, r);
    value[x] = value[lson[x]] + value[rson[x]];
}
void update(int old, int &x, int p, int v, int l, int r) {
    x = ++tot;
    lson[x] = lson[old], rson[x] = rson[old], value[x] = value[old] + v;
    if(l == r) return ;
    int m = (l+r) >> 1;
    if(p <= m) update(lson[x], lson[x], p, v, l, m);
    else update(rson[x], rson[x], p, v, m+1, r);
}
int query(int x, int y, int l, int r, int k) {
    if(l == r) return l;
    int m = (l+r) >> 1, cnt = value[lson[y]] - value[lson[x]];
    if(k <= cnt) return query(lson[x], lson[y], l, m, k);
    else return query(rson[x], rson[y], m+1, r, k-cnt);
}
int main() {
    while(~scanf("%d %d", &n, &m)) {
        vc.clear();        
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]), vc.pb(a[i]);
        sort(vc.begin(), vc.end());
        vc.erase(unique(vc.begin(), vc.end()), vc.end());
        for (int i = 1; i <= n; i++) {
           int id = lower_bound(vc.begin(), vc.end(), a[i]) - vc.begin() + 1;
           v[id] = a[i];
           a[i] = id;
        }
        tot = 0;
        build(root[0], 1, n);
        for (int i = 1; i <= n; i++) update(root[i-1], root[i], a[i], 1, 1, n);
        while(m--) {
            scanf("%d %d", &l, &r);
            vector<int> t; 
            if(r-l+1 > 50) {
                int up = 45;
                for (int k = 1; k <= up; ++k) t.pb(v[query(root[l-1], root[r], 1, n, (r-l+1-k+1))]);
            }
            else {
                for (int k = l; k <= r; ++k) t.pb(v[a[k]]);
                sort(t.begin(), t.end(), greater<int>());
            }
            LL ans = -1;
            //cout << t.size() << endl;
            for (int i = 0; i+2 < t.size(); ++i) {
                if(t[i+1]+t[i+2] > t[i]) {
                    ans = 1LL*t[i]+1LL*t[i+1]+1LL*t[i+2];
                    break;
                }
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
}
View Code

1012

思路:考慮到固定一個右端點,對於每種顏色,可行的區間是兩段區間(一段包含至少$k$個,一段一個都不包含),那么我們用線段樹維護這些區間,

最后找第一個被$c$種顏色覆蓋的位置。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
int n, c, k, a[N];
vector<int> vc[N];
struct Node {
    int v, lz;
}tree[N<<2];
inline void push_up(int rt) {
    tree[rt].v = max(tree[rt<<1].v, tree[rt<<1|1].v);
}
inline void push_down(int rt) {
    tree[rt<<1].v += tree[rt].lz;
    tree[rt<<1].lz += tree[rt].lz;
    tree[rt<<1|1].v += tree[rt].lz;
    tree[rt<<1|1].lz += tree[rt].lz;
    tree[rt].lz = 0;
}
void build(int rt, int l, int r) {
    tree[rt].lz = 0;
    if(l == r) {
        tree[rt].v = c;
        return ;
    }
    int m = l+r >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
void update(int L, int R, int x, int rt, int l, int r) {
    if(L <= l && r <= R) {
        tree[rt].v += x;
        tree[rt].lz += x;
        return ;
    }
    if(tree[rt].lz) push_down(rt);
    int m = l+r >> 1;
    if(L <= m) update(L, R, x, ls);
    if(R > m) update(L, R, x, rs);
    push_up(rt);
}
int query(int x, int rt, int l, int r) {
    if(l == r) return l;
    int m = l+r >> 1;
    if(tree[rt].lz) push_down(rt);
    if(tree[rt<<1].v == x) return query(x, ls);
    else if(tree[rt<<1|1].v == x) return query(x, rs);
    else return -1;
}
int main() {
    while(~scanf("%d %d %d", &n, &c, &k)) {
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for (int i = 1; i <= c; ++i) vc[i].clear();
        build(1, 1, n); int ans = 0;
        for (int i = 1; i <= n; ++i) {
            vc[a[i]].pb(i);
            update(vc[a[i]].size() == 1?1:(vc[a[i]][vc[a[i]].size()-2]+1), vc[a[i]].back(), -1, 1, 1, n);
            if(vc[a[i]].size() >= k) update(vc[a[i]].size() == k?1:(vc[a[i]][vc[a[i]].size()-k-1]+1), vc[a[i]][vc[a[i]].size()-k], 1, 1, 1, n);
            int p = query(c, 1, 1, n);
            if(~p)ans = max(ans, i-p+1);
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 2019 Multi-University Training Contest 3

Solved Pro.ID Title
  1001 Azshara's deep sea
    1002 Blow up the city
  1003 Yukikaze and Demons
  1004 Distribution of books
  1005 Easy Math Problem
  1006 Fansblog
  1007 Find the answer
    1008 Game
  1009 K Subsequence
  1010 Sindar's Art Exhibition
  1011 Squrirrel

1001

1002

思路:建反向圖,然后就是求DAG的從入度為0出發的支配樹。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
vector<int> g[N], rg[N];
queue<int> q;
int in[N], T, Q, n, m, u, v, dp[N], anc[N][18];
inline int lca(int u, int v) {
    if(dp[u] < dp[v]) swap(u, v);
    for (int i = 17; i >= 0; --i) if(dp[anc[u][i]] >= dp[v]) u = anc[u][i];
    if(u == v) return u;
    for (int i = 17; i >= 0; --i) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i];
    return anc[u][0];
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= m; ++i){
            scanf("%d %d", &u, &v);
            g[v].pb(u);
            in[u]++;
            rg[u].pb(v);
        }
        for (int i = 1; i <= n; ++i) if(!in[i]) q.push(i);
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            int l;
            if(rg[u].size() == 0) l = 0;
            else {
                l = rg[u][0];
                for (int i = 1; i < rg[u].size(); ++i) {
                    int v = rg[u][i];
                    l = lca(l, v);
                }
            }
            anc[u][0] = l;
            for (int i = 1; i < 18; ++i) anc[u][i] = anc[anc[u][i-1]][i-1];
            dp[u] = dp[l]+1;
            for (int v : g[u]) {
                in[v]--;
                if(!in[v]) q.push(v);
            }
        }
        scanf("%d", &Q);
        while(Q--) {
            scanf("%d %d", &u, &v);
            printf("%d\n", dp[u]+dp[v]-dp[lca(u, v)]);
        }
        for (int i = 0; i <= n; ++i) g[i].clear(), rg[i].clear(), in[i] = 0;
    }
    return 0;
}
View Code

1003

1004

隊友補了

1005

1006

思路:首先要知道一個公式:$(p-1)!\%p = p-1$。這個公式好像叫威爾遜定理。然后因為素數之間的距離很近,我們可以暴力往前找那個素數$Q$,

只要先預處理$1e7$以內的素數就可以了。最后把那個公式的階乘除到$Q!$,還有一點要注意$1e14$做乘法會爆,要用__int128或者快速乘。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e7 + 5;
LL MOD;
LL q_pow(__int128 n, __int128 k) {
    __int128 res = 1;
    while(k) {
        if(k&1) res = (res * n) % MOD;
        n = (n*n) % MOD;
        k >>= 1;
    }
    return (LL)res;
}
int prime[N], cnt;
bool not_p[N];
void init() {
    for (int i = 2; i < N; ++i) {
        if(!not_p[i]) prime[++cnt] = i;
        for (int j = 1; j <= cnt && i*prime[j] < N; ++j) {
            not_p[i*prime[j]] = true;
            if(i%prime[j] == 0) break;
        }
    }
}
int T;
int main() {
    init();
    scanf("%d", &T);
    while(T--) {
        scanf("%lld", &MOD);
        LL now;
        for (now = MOD-1; ; --now) {
            bool f = true;
            for (int j = 1; prime[j]*1LL*prime[j] <= now; ++j) {
                if(now%prime[j] == 0) {
                    f = false;
                    break;
                }
            }
            if(f) break;
        }
        __int128 ans = (MOD-1)%MOD;
        for (LL i = MOD-1; i > now; --i) ans = (ans * q_pow(i, MOD-2))%MOD;
        printf("%lld\n", (LL)ans);
    }
    return 0;
}
View Code

1007

思路:離散化+線段樹。對於每個位置在前$i-1$個數中,找一個$k$使得前$k$大加起來大於等於$sum_i-m$。為什么一做到這種題就想到Splay。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 2e5 + 10;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0;
LL sum[N];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sum[x] = sum[ch[x][0]] -val[x]*1LL*cnt[x] + sum[ch[x][1]];
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
void Find(int x) {
    if(!rt) return ;
    int cur = rt;
    while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
    Splay(cur);
}
void Insert(int x) {
    int cur = rt, p = 0;
    while(cur && val[cur] != x) {
        p = cur;
        cur = ch[cur][x>val[cur]];
    }
    if(cur) cnt[cur]++;
    else {
        cur = ++ncnt;
        if(p) ch[p][x>val[p]] = cur;
        fa[cur] = p;
        ch[cur][0] = ch[cur][1] = 0;
        val[cur] = x;
        sum[cur] = 0;
        cnt[cur] = sz[cur] = 1;
    }
    Splay(cur);
}
int get(LL k) {
    int cur = rt, now = 0;
    while(true) {
        if(ch[cur][0] && k <= sum[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sum[ch[cur][0]] + abs(val[cur])*1LL*cnt[cur]) k -= sum[ch[cur][0]] + abs(val[cur])*1LL*cnt[cur], now += sz[ch[cur][0]]+cnt[cur], cur = ch[cur][1];
        else {
            int tmp = (k-sum[ch[cur][0]]+abs(val[cur])-1)/abs(val[cur]);
//            cout << tmp << endl;
            now += sz[ch[cur][0]]+tmp;
            return now;
        }
    }
}
inline void init() {
    ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = val[0] = sum[0] = 0;
}
int n, m, T, a[N];
//void Output(int x) {
//    if(ch[x][0]) Output(ch[x][0]);
//    printf("%d ", val[x]);
//    if(ch[x][1]) Output(ch[x][1]);
//}
int main() {
    scanf("%d", &T);
    while(T--) {
        init();
        scanf("%d %d", &n, &m);
        LL s = 0;
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for (int i = 1; i <= n; ++i) {
            s += a[i];
            if(s <= m)printf("0");
            else printf("%d", get(s-m));
            Insert(-a[i]);
            if(i == n) printf(" \n");
            else printf(" ");
        }
    }
    return 0;
}
View Code

1008

隊友補了

1009

思路:最小費用流。關於建圖有一個優化的地方,每個位置和后面比他大元素連接時,這些比他大的元素構成遞減序列,這樣就可以少連很多條邊,那么要保證每個位置可以跑多次,只有第一次才有費用,可以在某些點之間(自行考慮)多連一條容量無窮,費用為0的邊。最后再加上Dijkstra的費用流板子,就可以跑$78ms$了。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 4e3 + 10;
const int INF = 0x3f3f3f3f;
struct edge {
    int to, cap, cost, rev;
};
int V, a[N];
vector<edge>g[N];
int h[N], dis[N], prevv[N], preve[N];
void add_edge(int u, int v, int cap, int cost) {
    g[u].pb({v, cap, cost, g[v].size()});
    g[v].pb({u, 0, -cost, g[u].size()-1});
}
int min_cost_flow(int s, int t, int f) {
    int res = 0;
    mem(h, 0);
    while(f > 0) {
        priority_queue<pii, vector<pii>, greater<pii> > q;
        mem(dis, 0x3f);
        dis[s] = 0;
        q.push({0, s});
        while(!q.empty()) {
            pii p = q.top();
            q.pop();
            int v = p.se;
            if(dis[v] < p.fi) continue;
            for (int i = 0; i < g[v].size(); ++i) {
                edge &e = g[v][i];
                if(e.cap > 0 && dis[e.to] > dis[v] + e.cost + h[v] - h[e.to]) {
                    dis[e.to] = dis[v] + e.cost + h[v] - h[e.to];
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    q.push({dis[e.to], e.to});
                }
            }
        }
        if(dis[t] == INF) return -1;
        for (int v = 0; v < V; ++v) h[v] += dis[v];
        int d = f;
        for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap);
        f -= d;
        res += d*h[t];
        for (int v = t; v != s; v = prevv[v]) {
            edge &e = g[prevv[v]][preve[v]];
            e.cap -= d;
            g[v][e.rev].cap += d;
        }
    }
    return res;
}
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                int n,k;
                scanf("%d%d", &n, &k);
                int s = 0, t = 2 * n + 1, ss = t+1;
                V = ss+1;
                for(int i=1; i<=n; i++) {
                    scanf("%d", &a[i]);
                    add_edge(i, i+n, 1, -1*a[i]);
                    add_edge(i, i+n, INF, 0);
                }
                for(int i=1; i<=n; i++) {
                    add_edge(s, i, 1, 0);
                    add_edge(i + n, t, 1, 0);
                    int now = INT_MAX;
                    for(int j=i+1; j<=n; j++) {
                        if(a[i] <= a[j] && a[j] < now) {
                            add_edge(i+n, j, INF, 0);
                            now = min(now, a[j]);
                        }
                    }
                }
                add_edge(ss, s, k, 0);
                printf("%lld\n", -min_cost_flow(ss, t, k));
                for (int i = 0;i < V; ++i) g[i].clear();
            }
            return 0;
}
View Code

1010

1011

隊友補了

2019 Multi-University Training Contest 4

Solved Pro.ID Title
  1001 AND Minimum Spanning Tree
  1002 Colored Tree
  1003 Divide the Stones
  1004 Enveloping Convex
  1005 Good Numbers
  1006 Horse
  1007 Just an Old Puzzle
  1008 K-th Closest Distance
  1009 Linear Functions
  1010 Minimal Power of Prime

1001

思路:如果$n==2^p-1$,那么最小權值是1;否則最小權值是0。$f_i$為最小的$2^p$使得$i\&{2}^{p} == 0$。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 2e5 + 5;
int T, n, p[21], ans[N];
int main() {
    p[0] = 1;
    for (int i = 1; i <= 20; ++i) p[i] = p[i-1]*2;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        int res = 0;
        bool f = true;
        for (int i = 1; i < 20; ++i) {
            if(n == p[i]-1) {
                f = false;
                break;
            }
        }
        if(f) res = 0;
        else res = 1;
        printf("%d\n", res);
        if(f) {
            for (int i = 2; i <= n; ++i) {
                if(i%2 == 0) ans[i] = 1;
                else {
                    int now = 0;
                    for (int j = 0; j <= 20; ++j) {
                        if(p[j] <= n && (p[j]&i) == 0) {
                            ans[i] = p[j];
                            break;
                        }
                    }
                }
            }
        }
        else {
            ans[n] = 1;
            for (int i = 2; i < n; ++i) {
                if(i%2 == 0) ans[i] = 1;
                else {
                    int now = 0;
                    for (int j = 0; j <= 20; ++j) {
                        if(p[j] <= n && (p[j]&i) == 0) {
                            ans[i] = p[j];
                            break;
                        }
                    }
                }
            }
        }
        for (int i = 2; i <= n; ++i) printf("%d%c", ans[i], " \n"[i==n]);
    }
    return 0;
}
View Code

1002

1003

思路:構造。打表找規律。

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
vector<int> vs[maxn];
int main(){
    int T; scanf("%d",&T);
    while(T--){
        int n,k; scanf("%d %d",&n,&k);
        if(n==k){
            if(n==1) { printf("yes\n"); printf("1\n");}
            else     { printf("no\n"); }
            continue;
        }
        ll num=1ll*(1+n)*n/2;
        if(num%k!=0){
            printf("no\n");
            continue;
        }
        int x=n/k;int c=1;
        if(x%2==1){
            if(k%2==0){
                printf("no\n");
                continue;
            }
            for(int i=1;i<=x;i++){
                if(i==1){
                    for(int j=1;j<=k;j++) { vs[j].push_back(c); c++;}
                    for(int j=k;j>=1;j-=2) { vs[j].push_back(c); c++;  }
                    for(int j=k-1;j>=1;j-=2){ vs[j].push_back(c); c++; }
                    for(int j=k-1;j>=1;j-=2){vs[j].push_back(c); c++; }
                    for(int j=k;j>=1;j-=2) {vs[j].push_back(c); c++; }
                    i++; i++;
                }
                else {
                    for(int j=1;j<=k;j++) { vs[j].push_back(c); c++;}
                    for(int j=k;j>=1;j--) {vs[j].push_back(c); c++;}
                    i++;
                }
            }
        }
        else {
             for(int i=1;i<=x;i++){
                for(int j=1;j<=k;j++) { vs[j].push_back(c); c++;}
                for(int j=k;j>=1;j--) {vs[j].push_back(c); c++;}
                i++;
            }
        }
        printf("yes\n");
        for(int i=1;i<=k;i++){
            for(int j=0;j<vs[i].size();j++){
                if(j!=0) printf(" ");
                printf("%d",vs[i][j]);
            }
            printf("\n"); vs[i].clear();
        }
    }
}
View Code

1004

1005

1006

思路:斜率優化dp。維護遞增斜率$\frac{dp[j]-dp[k]+s[k]-s[j]+j*sum[j]-k*sum[k]}{sum[j]-sum[k]}$,其中$sum_i$表示前綴和,$s_i$表示前綴和的前綴和。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e4 + 10;
int T, n, k, m, h[N];
vector<int> vc;
LL dp[N][55], sum[N], s[N];
deque<int> q[55];
inline LL up(int k, int j, int p) {
    return dp[j][p]-dp[k][p]+s[k]-s[j]+j*sum[j]-k*sum[k];
}
inline LL dw(int k, int j) {
    return sum[j]-sum[k];
}
inline bool g(int k, int j, LL c, int p) {
    return up(k, j, p) <= c*dw(k, j);
}
inline bool gg(int k, int j, int i, int p) {
    return up(k, j, p)*dw(j, i) >= up(j, i, p)*dw(k, j);
}
int main() {
    scanf("%d", &T);
    while(T--) {
        vc.clear();
        scanf("%d %d %d", &n, &k, &m);
        for (int i = 1; i <= n; ++i) scanf("%d", &h[i]), vc.pb(h[i]*(n-i+1)), sum[i] = sum[i-1]+h[i], s[i] = s[i-1]+sum[i];
        for (int i = 0; i <= n; ++i) for (int j = 0; j <= k+1; ++j) dp[i][j] = 1LL<<60;
        dp[0][0] = 0;
        sort(vc.begin(), vc.end(), greater<int>());
        LL ans = 0;
        for (int i = 0; i < m; ++i) ans += vc[i];
        for (int i = 0; i <= k+1; ++i) q[i].clear();
        q[0].push_back(0);
        for (int i = 1; i <= n; ++i) {
            for (int j = k; j >= 0; --j) {
                while(q[j].size() >= 2) {
                    int a = q[j].front();
                    q[j].pop_front();
                    int b = q[j].front();
                    if(g(a, b, i, j)) ;
                    else {
                        q[j].push_front(a);
                        break;
                    }
                }
                if(!q[j].empty()) {
                    int x = q[j].front();
                    dp[i][j+1] = dp[x][j]+s[i]-s[x]-(i-x)*sum[x];
                    while(q[j+1].size() >= 2) {
                        int b = q[j+1].back();
                        q[j+1].pop_back();
                        int a = q[j+1].back();
                        if(gg(a, b, i, j+1)) ;
                        else {
                            q[j+1].push_back(b);
                            break;
                        }
                    }
                    q[j+1].push_back(i);
                }
            }
        }
        LL tmp = 1LL<<60;
        for (int j = 1; j <= k+1; ++j) tmp = min(tmp, dp[n][j]);
        printf("%lld\n", ans-tmp);
    }
    return 0;
}
View Code

1007

思路:將0看成16,0每移動一個位置會改變奇數個逆序數,所以逆序數和移動距離奇偶性相同。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

int T, n, a[10][10];
vector<int> vc;
int main() {
    scanf("%d", &T);
    while(T--) {
        vc.clear();
        int ans = 0, d = 0;
        for (int i = 1; i <= 4; ++i) for (int j = 1; j <= 4; ++j) {
            scanf("%d", &a[i][j]);
            if(a[i][j] == 0) a[i][j] = 16, d = (4-i)+(4-j);
            vc.pb(a[i][j]);
        }

        for (int i = 0; i < vc.size(); ++i) {
            for (int j = i+1; j< vc.size(); ++j) {
                if(vc[i] > vc[j]) ans++;
            }
        }
        if(ans%2 == d%2) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
View Code

1008

思路:先建立一顆划分樹。然后對於每個查詢我們二分答案$mid$,那么就是找$L$到$R$這段區間有多少個數值在區間$[p-mid, p+mid]$,這個可以在划分樹上每個節點二分實現。

單次查詢復雜度$O(log(n)^3)$。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 1e5+9;
            int a[maxn];
            vector<int> vec[maxn<<2];
            inline void build(int le, int ri, int rt) {
                vec[rt].clear();
                if(le == ri) {
                    vec[rt].pb(a[le]);
                    return;
                }
                int mid = (le + ri) >> 1;
                build(le, mid, rt<<1);
                build(mid+1, ri, rt<<1|1);
                int p1 = 0, p2 = 0;
                while(p1 < vec[rt<<1].size() && p2 < vec[rt<<1|1].size()) {
                    if(vec[rt<<1][p1] < vec[rt<<1|1][p2]) {
                        vec[rt].pb(vec[rt<<1][p1]);
                        p1++;
                    }
                    else {
                        vec[rt].pb(vec[rt<<1|1][p2]);
                        p2++;
                    }
                }
                while(p1 < vec[rt<<1].size())  {
                        vec[rt].pb(vec[rt<<1][p1]);
                        p1++;
                    }
                while(p2 < vec[rt<<1|1].size()) {
                        vec[rt].pb(vec[rt<<1|1][p2]);
                        p2++;
                    }
                return ;
            }

            inline int query(int L, int R ,int x, int y, int le, int ri, int rt) {
                if(le >= L && ri <= R) return upper_bound(vec[rt].begin(), vec[rt].end(), y) - lower_bound(vec[rt].begin(), vec[rt].end(), x);
                int mid = (le + ri) >> 1;
                int res = 0;
                if(mid >= L)  res += query(L, R, x, y ,le, mid, rt<<1);
                if(mid < R) res += query(L, R, x, y, mid+1, ri, rt<<1|1);
                return res;
            }

int main(){
            int T; read(T);
            while(T--){
                int n,m;
                read(n); read(m);
                for(int i=1; i<=n; i++) read(a[i]);
                int X = 0;
                build(1, n, 1);

                for(int i=1; i<=m; i++) {
                    int tl, tr,tp,tk;
                    read(tl); read(tr); read(tp); read(tk);
                    int l,r,p,k;
                    l = tl ^ X;
                    r = tr ^ X;
                    p = tp ^ X;
                    k = tk ^ X;
                    int le = 0, ri = 1000000, mid = (le+ri) >> 1;
                    while(le < ri) {
                        if(query(l, r, p - mid, p + mid, 1, n, 1) >= k) ri = mid;
                        else le = mid+1;
                        mid = (le+ri) >> 1;
                    }
                    X = mid;
                    printf("%d\n", X);
                }
            }
            return 0;
}
View Code

1009

1010

思路:先把$5e3$以內的質因子篩掉,然后剩下的質因子的冪次最多是四次,特判一下$p^4$,$p^3$,$p^2$ ,$p_1^{2}p_2^2$這四種情況,

否則剩下的就是一個質因子冪次是1的情況。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e6 + 5, M = 5e3 + 5;
int T;
LL n;
vector<int> vc;
bool not_p[N];
int prime[N], cnt = 0;
inline void init() {
    for (int i = 2; i < N; ++i) {
        if(!not_p[i]) {
            prime[++cnt] = i;
            if(i < M) vc.pb(i);
        }
        for (int j = 1; j <= cnt && i * prime[j] < N; ++j ) {
            not_p[i*prime[j]] = true;
            if(i%prime[j] == 0) break;
        }
    }
}
int main() {
    init();
    scanf("%d", &T);
    while(T--) {
        scanf("%lld", &n);
        int ans = 1000;
        for (int x : vc) {
            int cnt = 0;
            while(n%x == 0) n /= x, ++cnt;
            if(cnt) ans = min(ans, cnt);
        }
        if(n != 1) {
            bool f = false;
            LL x = pow(n*1.0, 1.0/4);
            while(x*x*x*x < n) ++x;
            while(x*x*x*x > n) --x;
            if(x*x*x*x == n && !not_p[x]) ans = min(ans, 4), f = true;

            if(!f) {
                x = pow(n*1.0, 1.0/3);
                while(x*x*x < n) ++x;
                while(x*x*x > n) --x;
                if(x*x*x == n && !not_p[x]) ans = min(ans, 3), f = true;
            }

            if(!f) {
                x = sqrt(n*1.0);
                while(x*x < n) ++x;
                while(x*x > n) --x;
                if(x*x == n) ans = min(ans, 2), f = true;
            }

            if(!f) ans = min(ans, 1);
        }
        if(ans == 1000) ans = 1;
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 2019 Multi-University Training Contest 5

Solved Pro.ID Title
  1001 fraction
  1002 three arrays
  1003 geometric problem
  1004 equation
  1005 permutation 1
  1006 string matching
  1007 permutation 2
    1008 line symmetric
  1009 discrete logarithm problem
  1010 find hidden array

1001

思路:按照官方題解化出的式子,就是51Nod 1187 尋找分數,用類歐求解。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

int T;
LL a, b, c, d, p, q, P, X;
//a/b < p/q < c/d
void solve(LL a, LL b, LL c, LL d) {
    if(a == 0) {
        p = 1;
        q = d/c+1;
        return ;
    }
    if(a >= b) {
        solve(a%b, b, c-(a/b)*d, d);
        p += (a/b)*q;
        return ;
    }
    if(c > d) {
        p = q = 1;
        return ;
    }
    solve(d, c, b, a);
    swap(p, q);
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%lld %lld", &P, &X);
        a = P, b = X, c = P, d = X-1;
        solve(a, b, c, d);
        printf("%lld/%lld\n", p*X-P*q, p);
    }
    return 0;
}
View Code

1002

思路:01字典樹上貪心,建兩顆字典樹,每次能同方向走就同方向走。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
int a[N], b[N], n, T;
vector<int> vc;
struct Trie {
    int trie[N*30][2], cnt[N*30], tot;
    inline void clr() {
        for (int i = 0; i <= tot; ++i) trie[i][0] = trie[i][1] = cnt[i] = 0;
        tot = 0;
    }
    inline void ins(int x) {
        int rt = 0;
        for (int i = 29; i >= 0; --i) {
            int id = (x>>i)&1;
            if(!trie[rt][id]) trie[rt][id] = ++tot;
            rt = trie[rt][id];
            cnt[rt]++;
        }
    }
}A, B;
inline int solve() {
    int ra = 0, rb = 0, res = 0;
    for (int i = 29; i >= 0; --i) {
        if(A.cnt[A.trie[ra][0]] && B.cnt[B.trie[rb][0]]) {
            ra = A.trie[ra][0];
            rb = B.trie[rb][0];
            A.cnt[ra]--;
            B.cnt[rb]--;
        }
        else if(A.cnt[A.trie[ra][1]] && B.cnt[B.trie[rb][1]]) {
            ra = A.trie[ra][1];
            rb = B.trie[rb][1];
            A.cnt[ra]--;
            B.cnt[rb]--;
        }
        else if(A.cnt[A.trie[ra][0]] && B.cnt[B.trie[rb][1]]){
            ra = A.trie[ra][0];
            rb = B.trie[rb][1];
            A.cnt[ra]--;
            B.cnt[rb]--;
            res |= 1<<i;
        }
        else {
            ra = A.trie[ra][1];
            rb = B.trie[rb][0];
            A.cnt[ra]--;
            B.cnt[rb]--;
            res |= 1<<i;
        }
    }
    return res;
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        A.clr(), B.clr();
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), A.ins(a[i]);
        for (int i = 1; i <= n; ++i) scanf("%d", &b[i]), B.ins(b[i]);
        vc.clear();
        for (int i = 1; i <= n; ++i) vc.pb(solve());
        sort(vc.begin(), vc.end());
        for (int i = 0; i < n; ++i) printf("%d%c", vc[i], " \n"[i+1==n]);
    }
    return 0;
}
View Code

1003

1004

思路:暴力。按$\frac{-b}{a}$排序,然后枚舉以相鄰兩個值作為$x$的范圍。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
int n, T, c, suma[N], sumb[N], sufa[N], sufb[N];
pii a[N];
vector<pii> res;
bool cmp(pii x, pii y) {
    return -x.se*1LL*y.fi < -y.se*1LL*x.fi;
}
bool _cmp(pii x, pii y) {
    return x.se*1LL*y.fi < y.se*1LL*x.fi;
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &c);
        for (int i = 1; i <= n; ++i) scanf("%d %d", &a[i].fi, &a[i].se);
        sort(a+1, a+1+n, cmp);
        for (int i = 1; i <= n; ++i) suma[i]=suma[i-1]+a[i].fi, sumb[i] = sumb[i-1]+a[i].se;
        sufa[n+1] = sufb[n+1] = 0;
        for (int i = n; i >= 1; --i) sufa[i] = sufa[i+1]-a[i].fi, sufb[i] = sufb[i+1]-a[i].se;
        bool f = false;
        for (int i = 0; i <= n; ++i) {
            LL sa = suma[i]+sufa[i+1];
            LL sb = sumb[i]+sufb[i+1];
            LL up = c-sb;
            LL dw = sa;
            //cout << sa << " " << up << endl;
            if(dw == 0) {
                if(up == 0) {
                    //cout << a[i].se*1LL*a[i+1].fi << " 11111 " <<  a[i].se*1LL*a[i-1].fi << endl;
                    if(i == 0 || i == n) f = true;
                    else if(a[i].se*1LL*a[i+1].fi != a[i+1].se*1LL*a[i].fi) f = true;
                }
            }
            else {
                LL d = __gcd(dw, up);
                dw /= d, up /= d;
                if(dw < 0) dw = -dw, up = -up;
                if(dw > 0) {
                    if(i == 0) {
                        if(up*a[i+1].fi <= -a[i+1].se*dw) res.pb(dw, up);
                    }
                    else if(i == n) {
                        if(up*a[i].fi >= -a[i].se*dw) res.pb(dw, up);
                    }
                    else {
                        if(up*a[i+1].fi <= -a[i+1].se*dw && up*a[i].fi >= -a[i].se*dw) res.pb(dw, up);
                    }
                }
                else {
                    if(i == 0) {
                        if(up*a[i+1].fi >= -a[i+1].se*dw) res.pb(dw, up);
                    }
                    else if(i == n) {
                        if(up*a[i].fi <= -a[i].se*dw) res.pb(dw, up);
                    }
                    else {
                        if(up*a[i+1].fi >= -a[i+1].se*dw && up*a[i].fi <= -a[i].se*dw) res.pb(dw, up);
                    }
                }
            }
        }
        if(f) printf("-1\n");
        else {
            sort(res.begin(), res.end());
            res.erase(unique(res.begin(), res.end()), res.end());
            sort(res.begin(), res.end(), _cmp);
            if(res.size() != 0) {
                printf("%d ", (int)res.size());
                int tot = 0;
                for (pii p : res) {
                    ++tot;
                    printf("%d/%d%c", p.se, p.fi, " \n"[tot==res.size()]);
                }
            }
            else printf("0\n");
        }
        res.clear();
    }
    return 0;
}
View Code

1005

思路:分類討論,當$k$大於$(n-2)!$時,$n!$不會太大,直接暴力算,否則固定第一個為$n$,第二個為$1$,算出后面$n-2$個數排列的第$k$大。

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e4+10;
int k[maxn];
int a[maxn*55][21];
int n,num, id[maxn*55];
bool cmp(int x, int y) {
    for (int i = 1; i < n; ++i) {
        if(a[x][i]-a[x][i-1] < a[y][i]-a[y][i-1]) return 1;
        else if(a[x][i]-a[x][i-1] > a[y][i]-a[y][i-1]) return 0;
    }
    return 1;
}
int main(){
     int T; scanf("%d",&T);
     while(T--){
        scanf("%d %d",&n,&num);
        int temp=0;
        ll t=1;
        for(int i=1;i<n-1;i++) t=t*i;
        int tot = 0;
        if(t>=num){
            k[0] = n;
            k[1] = 1;
            for (int i = 2; i < n; ++i) k[i] = i;
            do{
                tot++;
                for(int i=0;i<=n-1;i++) a[tot][i]=k[i];
                if(tot >= 40320) break;
            }
            while(next_permutation(k+2,k+n));
        }
        else {
            for(int i=0;i<=n-1;i++) k[i]=i+1;
            do{
                tot++;
                for(int i=0;i<=n-1;i++) a[tot][i]=k[i];
            }
            while(next_permutation(k,k+1+n-1));
        }
        for (int i = 1; i <= tot; ++i) id[i] = i;
        nth_element(id+1, id+num, id+1+tot, cmp);
        for (int i = 0; i < n; ++i) printf("%d%c", a[id[num]][i], " \n"[i==n-1]);
     }
}
View Code

1006

思路:exkmp。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e6 + 5;
int T, n;
char s[N], t[N];
int nxt[N], ex[N];
void GETNEXT(char *str) {
    int i = 0, j, po, len=strlen(str);
    nxt[0] = len;
    while(str[i] == str[i+1] && i+1 < len) i++;
    nxt[1] = i;
    po = 1;
    for(i = 2; i < len; i++) {
        if(nxt[i-po] + i < nxt[po] + po)
        nxt[i] = nxt[i-po];
        else {
            j=nxt[po] + po - i;
            if(j < 0) j = 0;
            while(i + j < len && str[j] == str[j+i])
            j++;
            nxt[i] = j;
            po = i;
        }
    }
}
void EXKMP(char *s1,char *s2)
{
    int i = 0, j, po, len = strlen(s1), l2=strlen(s2);
    GETNEXT(s2);
    while(s1[i] == s2[i] && i < l2 && i < len) i++;
    ex[0] = i;
    po = 0;
    for(i = 1; i < len; i++)
    {
        if(nxt[i-po] + i < ex[po] + po) ex[i]=nxt[i-po];
        else {
            j = ex[po] + po - i;
            if(j < 0) j = 0;
            while(i + j < len && j < l2 && s1[j+i] == s2[j]) j++;
            ex[i] = j;
            po = i;
        }
    }
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%s", s);
        n = strlen(s);
        for (int i = 0; i <= n; ++i) t[i] = s[i];
        EXKMP(s, t);
        LL ans = 0;
        for (int i = 1; i < n; ++i) {
            if(ex[i]+i == n) ans += ex[i];
            else ans += ex[i]+1;
            //cout << ans << endl;
        }
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

1007

思路:我們發現從$x$到$x+1$以及$y-1$到$y$的方案是固定的(每次跳兩格到邊界再跳回來),那么答案只根$x$和$y$的間距有關系了,我們打表找規律。

然后再處理一些特殊情況就好了。

代碼:

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
const int maxn=1e5+10;
int a[maxn];
int f[maxn];
int main(){
    //a[1]=1; a[2]=2; a[3]=3; a[4]=4;
    f[0]=1; f[1]=1; f[2]=1; f[3]=2; f[4]=3;
    for(int i=5;i<maxn;i++){
       f[i]=f[i-1]+f[i-3];        f[i]=f[i]%mod;
        //a[i]=a[i-1]+f[i];          a[i]=a[i]%mod;
    }
    //for(int i=1;i<=10;i++) cout<<f[i]<<endl;
    int T; scanf("%d",&T);
    while(T--){
        int n,x,y; scanf("%d %d %d",&n,&x,&y);
        if(x+1==y){
            if(x>=2 && x<=n-2) printf("0\n");
            else               printf("1\n");
            continue;
        }
        if(x!=1) x++;
        if(y!=n) y--;
        printf("%d\n",f[y-x]);
    }
}
View Code

1008

隊友補了

1009

1010

2019 Multi-University Training Contest 6

Solved Pro.ID Title
  1001 Salty Fish
  1002 Nonsense Time
  1003 Milk Candy
  1004 Speed Dog
  1005 Snowy Smile
  1006 Faraway
  1007 Support or Not
  1008 TDL
  1009 Three Investigators
  1010 Ridiculous Netizens
  1011 11 Dimensions
  1012 Stay Real

1001

1002

思路:由於數據隨機,所以最長上升子序列期望長度是$\sqrt{n}$。所以從后往前算,每次如果一個元素是在最長上升子序列中就重新算一邊最長上升子序列。

復雜度$\sqrt{n}*n*log(n)$。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 5e4 + 5;
const int INF = 0x3f3f3f3f;
int  a[N], k[N], dp[N], ans[N], pre[N], n, T;
bool vis[N]; ///遞增序列中
bool vv[N]; ///被凍住
inline int cal() {
    fill(dp, dp+n, INF);
    fill(pre, pre+n+1, 0);
    fill(vis+1, vis+n+1, false);
    for (int i = 1; i <= n; ++i) {
        if(vv[a[i]]) continue;
        int p = lower_bound(dp, dp+n, a[i])-dp;
        if(p) pre[a[i]] = dp[p-1];
        dp[p] = a[i];
    }
    int p = lower_bound(dp, dp+n, INF)-dp;
    int t = dp[p-1];
    while(t) {
        vis[t] = true;
        t = pre[t];
    }
    return p;
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for(int i = 1; i <= n; ++i) scanf("%d", &k[i]);
        fill(vv+1, vv+n+1, false);
        int c = cal();
        for (int i = n; i >= 1; --i) {
            ans[i] = c;
            vv[a[k[i]]] = true;
            if(vis[a[k[i]]]) c = cal();
        }
        for (int i = 1; i <= n; ++i) printf("%d%c", ans[i], " \n"[i==n]);
    }
    return 0;
}
View Code

1003

1004

1005

思路:枚舉上下邊界,用線段樹維護最大字段和。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 2e3 + 10;
int n, T;
LL v[N][N];
vector<int> vx, vy;
vector<pair<int,LL>> vc[N];
piii a[N];
struct Node {
    LL mx, sum, l, r;
}tree[N<<2];
inline void push_up(int rt) {
    tree[rt].sum = tree[rt<<1].sum+tree[rt<<1|1].sum;
    tree[rt].l = max(tree[rt<<1].l, tree[rt<<1].sum+tree[rt<<1|1].l);
    tree[rt].r = max(tree[rt<<1|1].r, tree[rt<<1|1].sum+tree[rt<<1].r);
    tree[rt].mx = max(max(tree[rt<<1].mx, tree[rt<<1|1].mx), tree[rt<<1].r+tree[rt<<1|1].l);
}
void build(int rt, int l, int r) {
    tree[rt].mx = tree[rt].sum = tree[rt].l = tree[rt].r = 0;
    if(l == r) return ;
    int m = l+r >> 1;
    build(ls);
    build(rs);
}
void update(int p, LL x, int rt, int l, int r) {
    if(l == r) {
        tree[rt].sum += x;
        tree[rt].l = max(0LL, tree[rt].sum);
        tree[rt].r = max(0LL, tree[rt].sum);
        tree[rt].mx = max(0LL, tree[rt].sum);
        return ;
    }
    int m = l+r >> 1;
    if(p <= m) update(p, x, ls);
    else update(p, x, rs);
    push_up(rt);
}
int main() {
    scanf("%d", &T);
    while(T--) {
        vx.clear();
        vy.clear();
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%d %d %d", &a[i].fi.fi, &a[i].fi.se, &a[i].se);
            vx.pb(a[i].fi.fi);
            vy.pb(a[i].fi.se);
        }

        sort(vx.begin(), vx.end());
        vx.erase(unique(vx.begin(), vx.end()), vx.end());
        sort(vy.begin(), vy.end());
        vy.erase(unique(vy.begin(), vy.end()), vy.end());
        for (int i = 1; i <= n; ++i) {
            a[i].fi.fi = lower_bound(vx.begin(), vx.end(), a[i].fi.fi)-vx.begin()+1;
            a[i].fi.se = lower_bound(vy.begin(), vy.end(), a[i].fi.se)-vy.begin()+1;
        }
        int upx = vx.size(), upy = vy.size();
        for (int i = 0; i <= upx; ++i) for (int j = 0; j <= upy; ++j) v[i][j] = 0;
        for (int i = 1; i <= n; ++i) v[a[i].fi.fi][a[i].fi.se] += a[i].se;
        LL ans = 0;
        for (int i = 1; i <= upx; ++i) {
            for (int j = 1; j <= upy; ++j) {
                if(v[i][j]) vc[i].pb(j, v[i][j]);
            }
        }
        for (int i = 1; i <= upx; ++i) {
            build(1, 1, upy);
            for (int j = i; j <= upx; ++j) {
                for (auto p : vc[j]) update(p.fi, p.se, 1, 1, upy);
                ans = max(ans, tree[1].mx);
            }
        }
        printf("%lld\n", ans);
        for (int i = 0; i <= upx; ++i) vc[i].clear();
    }
    return 0;
}
View Code

1006

思路:先對橫縱坐標排序去重,然后枚舉每一個小矩形,對於每個小矩形,它的循環節是60*60的。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 15;
int T, n, m;
int x[N], y[N], k[N], t[N];
int sum[65][65];
vector<int> vx, vy;
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        vx.clear(), vy.clear();
        for (int i = 1; i <= n; ++i) scanf("%d %d %d %d", &x[i], &y[i], &k[i], &t[i]), vx.pb(x[i]), vy.pb(y[i]);
        vx.pb(-1), vx.pb(m);
        vy.pb(-1), vy.pb(m);
        sort(vx.begin(), vx.end());
        sort(vy.begin(), vy.end());
        vx.erase(unique(vx.begin(), vx.end()), vx.end());
        vy.erase(unique(vy.begin(), vy.end()), vy.end());
        LL ans = 0;
        for (int i = 1; i < vx.size(); ++i) {
            for (int j = 1; j < vy.size(); ++j) {
                int x1 = vx[i-1]+1, y1 = vy[j-1]+1;
                int x2 = vx[i], y2 = vy[j];
                for (int dx = 1; dx <= 60; ++dx) {
                    for (int dy = 1; dy <= 60; ++dy) {
                        bool f = true;
                        for (int p = 1; p <= n; ++p) if((abs(x[p]-(x1+dx-1))+abs(y[p]-(y1+dy-1)))%k[p] != t[p]) {f = false; break;}
                        if(f) sum[dx][dy] = sum[dx-1][dy]+sum[dx][dy-1]-sum[dx-1][dy-1]+1;
                        else sum[dx][dy] = sum[dx-1][dy]+sum[dx][dy-1]-sum[dx-1][dy-1];
                    }
                }
                int dx = (x2-x1+1), dy = (y2-y1+1);
                ans += (dx/60)*1LL*(dy/60)*sum[60][60];
                ans += sum[dx%60][dy%60];
                ans += (dx/60)*1LL*sum[60][dy%60];
                ans += (dy/60)*1LL*sum[dx%60][60];
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

1007

1008

思路:暴力枚舉

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main(){
   int T; scanf("%d",&T);
   while(T--){
      ll k,m; scanf("%lld %lld",&k,&m);
      int flag=0;
      for(ll i=max(1ll,k-1000);i<=k+1000;i++){
            int tot=0;
            for(ll j=i+1;;j++){
                if(__gcd(i,j)==1) {
                    tot++;
                    if(tot==m){
                        if( (i^(j-i)^k)==0){
                            flag=1;
                            printf("%lld\n",i);
                        }
                        break;
                    }
                }
            }
            if(flag) break;
      }
      if(flag==0) printf("-1\n");
   }
}
View Code

1009

思路:每次向楊氏圖表中第一層插入a[i]個a[i],將大於a[i]的頂到下一層(具體看題解),楊氏圖表前5層個數就是答案。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
#define ll long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
int a[N], T, n;
map<int, LL> mp[5];
LL ans = 0;
inline void ins(int x, int cnt, int a) {
    if(x == 5) return ;
    map<int, LL>:: iterator it;
    while(cnt) {
        it = mp[x].upper_bound(a);
        if(it == mp[x].end()) {
            ans += cnt;
            mp[x][a] += cnt;
            cnt = 0;
        }
        else {
            int mn = min((LL)cnt, it->se);
            it->se -= mn;
            if((it->se) == 0) mp[x].erase(it);
            ins(x+1, mn, it->fi);
            mp[x][a] += mn;
            cnt -= mn;
        }
    }
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for (int i = 0; i < 5; ++i) mp[i].clear();
        ans = 0;
        for (int i = 1; i <= n; ++i) {
            ins(0, a[i], a[i]);
            printf("%lld%c", ans, " \n"[i==n]);
        }
    }
    return 0;
}
View Code

1010

1011

思路:dp

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 5e4+9;
            ll big = 1e18;
            ll dp[maxn][22];
            ll md[maxn],mdd[maxn];
            char str[maxn];
            vector<int>vec;
int main(){
            md[0] = 1;
            for(int i=1; i<maxn; i++) md[i] = md[i-1] * 10 % mod;
            int T;      scanf("%d", &T);
            while(T--) {
                int n,m,q;
                scanf("%d%d%d", &n, &m, &q);
                mdd[0] = 1;

                for(int i=1; i<maxn; i++) mdd[i] = mdd[i-1] * 10 % m;

                scanf("%s", str+1);
                ll sum = 0, tp = 0;
                vec.clear();
                for(int i=0; i<=n; i++) {
                    for(int j=0; j<m; j++) dp[i][j] = 0;
                }

                for(int i=n; i>=1; i--) {
                    if(str[i] == '?') {
                        if(vec.size() < 50) vec.pb(i);
                    }
                    else {
                        sum = (sum + md[n-i] * (str[i] - '0') % mod) % mod;
                        tp = (tp + mdd[n-i] * (str[i] - '0') % m) % m;
                    }
                }
                dp[0][tp] = 1;

                int all = vec.size();
                for(int i=1; i<=all; i++) {
                    int id = vec[i-1];
                    for(int j=0; j<10; j++) {
                        int up = mdd[n - id] * j % m;

                        for(int k=0; k<m; k++) {
                            ll tmp = dp[i][k] + dp[i - 1][(k - up + m) % m];
                            if(tmp <= big) {
                                dp[i][k] = tmp;
                            }
                            else dp[i][k] = big+1;
                        }
                    }
                }
//
//                for(int i=1; i<=all; i++) {
//                    for(int j=0; j<m; j++) {
//                        cout<<dp[i][j]<<" ";
//                    }
//                    cout<<endl;
//                }

                while(q--) {
                    ll cur = sum;
                    int flag = 1;
                    int y = 0;
                    ll k;

                    scanf("%lld", &k);
                    k--;
                    for(int i=all; i>=1; i--) {
                        int id = vec[i-1];
                        int flag = 1;
                        for(int j=0; j<10; j++) {
                            int tmp = (y + j * mdd[n-id] % m) % m;
                            if(dp[i-1][(m - tmp) % m] > k) {
                                y = tmp;
                                cur = (cur + j * md[n-id] % mod) % mod;
                                flag = 0;
                                break;
                            }
                            else {
                                k -= dp[i-1][(m - tmp) % m];
                            }
                        }
                        if(flag) {k=1; break;}
                    }
                    if(k) puts("-1");
                    else
                    printf("%lld\n", cur);
                }
            }
            return 0;
}
View Code

1012

思路:優先隊列模擬

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 1e5+9;
            priority_queue<pll>que;
            int du[maxn], a[maxn];
int main(){
            int T;      scanf("%d", &T);
            while(T--) {
                int n;
                scanf("%d", &n);
                ll s1 = 0, s2 = 0;
                for(int i=0; i<=n; i++) du[i] = 0;
                for(int i=1; i<=n; i++) {
                    scanf("%d", &a[i]);
                    du[i/2] ++;
                }
                while(!que.empty()) que.pop();
                for(int i=1; i<=n; i++) if(!du[i]) que.push(pll(a[i], i));
                int flag = 1;
                while(!que.empty()) {
                    pll f = que.top(); que.pop();
                    if(flag) {s1 += f.fi; flag = 0;}
                    else {s2+=f.fi;flag = 1;}
                    int u = f.se;
                    du[u/2] --;
                    if(du[u/2] == 0) que.push(pll(a[u/2], u/2));
                }
                printf("%lld %lld\n", s1, s2);

            }
            return 0;
}
View Code

2019 Multi-University Training Contest 7

Solved Pro.ID Title
  1001 A + B = C
  1002 Bracket Sequences on Tree
  1003 Cuber Occurrence
  1004 Data Structure Problem
  1005 Equation
  1006 Final Exam
  1007 Getting Your Money Back
  1008 Halt Hater
  1009 Intersection of Prisms
  1010 Just Repeat
  1011 Kejin Player

1001

思路:如果將$A$、$B$、$C$的后導零去掉,那么公式只有$A+B=C*10^z$,$A*10^x+B=C$,$A+B*10^y=C$三種情況,那么hash搞一搞。

代碼:

#include<bits/stdc++.h>
#define LL long long
#define pb emplace_back
using namespace std;
const int MOD = 1e9 + 7;
const int M2 = 1085438567;
const int BS = 2e9;
const int N = 1e5 + 5;
LL p[N], p2[N];
LL q_pow(LL n, LL k, LL MOD) {
    LL res = 1;
    while(k) {
        if(k&1) res = (res*n) %MOD;
        n = (n*n)%MOD;
        k >>= 1;
    }
    return res;
}
unordered_map<LL, int> mp;
void init() {
    p[0] = 1;
    p2[0] = 1;
    for (int i = 1; i < N; ++i) p[i] = p[i-1]*10%MOD, p2[i] = p2[i-1]*10%M2;
    for (int i = 0; i < N; ++i) mp[p[i]*BS+p2[i]] = i;
}
int T;
char a[N], b[N], c[N];
LL A, B, C, AA, BB, CC;
int main() {
    init();
    scanf("%d", &T);
    while(T--) {
        scanf("%s", a);
        scanf("%s", b);
        scanf("%s", c);
        int la = strlen(a), lb = strlen(b), lc = strlen(c);
        int ca = 0, cb = 0, cc = 0;
        A = B = C = AA = BB = CC = 0;
        while(a[la-1] == '0') --la, ++ca;
        while(b[lb-1] == '0') --lb, ++cb;
        while(c[lc-1] == '0') --lc, ++cc;
        for (int i = 0; i < la; ++i) A = (A*10+a[i]-'0')%MOD, AA = (AA*10+a[i]-'0')%M2;
        for (int i = 0; i < lb; ++i) B = (B*10+b[i]-'0')%MOD, BB = (BB*10+b[i]-'0')%M2;
        for (int i = 0; i < lc; ++i) C = (C*10+c[i]-'0')%MOD, CC = (CC*10+c[i]-'0')%M2;
        int x, y, z;
        bool f = false;
        LL t = (A+B)*q_pow(C, MOD-2, MOD)%MOD;
        LL tt = (AA+BB)*q_pow(CC, M2-2, M2)%M2;
        if(mp.find(t*BS+tt) != mp.end()) {
            x = 0;
            y = 0;
            z = mp[t*BS+tt];
            f = true;
        }
        t = ((C-B)*q_pow(A, MOD-2, MOD)%MOD+MOD)%MOD;
        tt = ((CC-BB)*q_pow(AA, M2-2, M2)%M2+M2)%M2;
        if(mp.find(t*BS+tt) != mp.end()) {
            x = mp[t*BS+tt];
            y = 0;
            z = 0;
            f = true;
        }
        t = ((C-A)*q_pow(B, MOD-2, MOD)%MOD+MOD)%MOD;
        tt = ((CC-AA)*q_pow(BB, M2-2, M2)%M2+M2)%M2;
        if(mp.find(t*BS+tt) != mp.end()) {
            x = 0;
            y = mp[t*BS+tt];
            z = 0;
            f = true;
        }
        x += max(ca, max(cb, cc)) - ca;
        y += max(ca, max(cb, cc)) - cb;
        z += max(ca, max(cb, cc)) - cc;
        if(f) printf("%d %d %d\n", x, y, z);
        else printf("-1\n");
    }
    return 0;
}
View Code

1002

1003

1004

1005

1006

思路:出題人要讓你做不出$k$道題,只能讓你復習時間最短的$n-k+1$道題都做不出,但是如果我復習時間最短的$n-k+1$道題的時間和是$m+1$,

你復習時間最短的$n-k+1$道題就至少有一道可以做出,所以公式是$m+1+(k-1)*\left\lceil\frac{m+1}{n-k+1}\right\rceil$。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

int T;
LL n, m, k;
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%lld %lld %lld", &n, &m, &k);
        LL B;
        if((m+1)%(n-k+1)) B = (m+1)/(n-k+1)+1;
        else B = (m+1)/(n-k+1);
        printf("%lld\n", B*(k-1)+m+1);
    }
    return 0;
}
View Code

1007

1008

思路:將一個格子看成一個點(可以一直往右走形成一個環),然后問題就轉換成從原點到$(x, y),(x-1, y),(x, y+1),(x-1, y+1)$的最小花費。

這樣轉換后一個點往上下左右走一步的花費是$b$,斜着走一步的最小花費是$c=min(2*b, a)$。然后優先斜着走,再直着走,直着走的時候,

每次優先兩步一起走(花費$min(2*c,2*b)$),最后走一步。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

int T;
LL a, b, x, y, c;
inline LL cal(LL x, LL y) {
    x = abs(x), y = abs(y);
    LL d = min(x, y), ans = 0;
    x -= d;
    y -= d;
    ans += d*c;
    ans += x/2*min(2*c, 2*b) + (x%2?b:0);
    ans += y/2*min(2*c, 2*b) + (y%2?b:0);
    return ans;
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%lld %lld %lld %lld", &a, &b, &x, &y);
        LL ans = 4e18;
        c = min(a, 2*b);
        ans = min(ans, cal(x, y));
        ans = min(ans, cal(x-1, y));
        ans = min(ans, cal(x-1, y+1));
        ans = min(ans, cal(x, y+1));
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

1009

1010

思路:貪心,對方的損失相當於你的獲得,所以對於每種顏色,把自己的個數和對方的個數加起來,就是總的貢獻,然后按貢獻排序。

代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int b[maxn];
unordered_map<int,int> mp,tf;
unsigned long long k1, k2;
unsigned long long rng() {
    unsigned long long k3 = k1, k4 = k2;
    k1 = k4;
    k3 ^= k3 << 23;
    k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
    return k2 + k4;
}
bool cmp1(pair<int,int> pa,pair<int,int> pb){
    return pa.first+pa.second>pb.first+pb.second;
}
pair<int,int> pa[maxn];
int main(){
    int  T; scanf("%d",&T);
    while(T--){
        mp.clear();
        tf.clear();
        int n,m,p;
        int num1=0;
        int num2=0;
        scanf("%d %d %d",&n,&m,&p);
        if(p==1){
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            for(int i=1;i<=m;i++) scanf("%d",&b[i]);
        }
        else {
            int mod;
            scanf("%llu%llu%d", &k1, &k2, &mod);
            for (int i = 1; i <= n; ++i)  a[i] = rng() % mod;
            scanf("%llu%llu%d", &k1, &k2, &mod);
            for (int i = 1; i <= m; ++i)  b[i] = rng() % mod;

        }
        for(int i=1;i<=n;i++){
            mp[a[i]]++;
        }
        for(int i=1;i<=m;i++){
            tf[b[i]]++;
        }
        int tot=0;
        for(int i=1;i<=n;i++){
            if(mp[a[i]] && tf[a[i]]){
                pa[++tot].first=mp[a[i]];
                 pa[tot].second=tf[a[i]];
                mp[a[i]]=0; tf[a[i]]=0;
            }
            else num1+=mp[a[i]],mp[a[i]]=0;
        }
        for(int i=1;i<=m;i++){
            num2+=tf[b[i]]; tf[b[i]]=0;
        }
        sort(pa+1,pa+1+tot,cmp1);
        for(int i=1;i<=tot;i++){
            if(i%2==1){
                num1+=pa[i].first+pa[i].second;
                num2+=pa[i].second;
            }
            else {
                num1+=pa[i].first;
                num2+=pa[i].first+pa[i].second;
            }
        }
        if(num1>num2) printf("Cuber QQ\n");
        else          printf("Quber CC\n");
    }
}
View Code

1011

思路:推相鄰兩個之間轉移的花費公式。

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+10;
ll f[maxn];
ll num[maxn];
int quick(int x,int n){
    int ans=1;
    while(n){
        if(n&1)ans=1ll*ans*x%mod;
        x=1ll*x*x%mod;
        n=n/2;
    } return ans;
}
struct FastIO {
    static const int S = 4e6;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar() {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos++];
    }
    inline int xuint() {
        int c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x;
    }
    inline int xint()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    inline void xstring(char *s)
    {
        int c = xchar();
        while (c <= 32) c = xchar();
        for (; c > 32; c = xchar()) * s++ = c;
        *s = 0;
    }
    inline void wchar(int x)
    {
        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
        wbuf[wpos++] = x;
    }
    inline void wint(int x)
    {
        if (x < 0) wchar('-'), x = -x;
        char s[24];
        int n = 0;
        while (x || !n) s[n++] = '0' + x % 10, x /= 10;
        while (n--) wchar(s[n]);
        wchar('\n');
    }
    inline void wstring(const char *s)
    {
        while (*s) wchar(*s++);
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
} io;
int main(){
    int T;T=io.xint();
    while(T--){
        int n,q;  n=io.xint();  q=io.xint();
        for(int i=1;i<=n;i++){
            int l,r,x,a;// scanf("%d %d %d %d",&l,&r,&x,&a);
            l=io.xint(); r=io.xint(); x=io.xint(); a=io.xint();
            int invr=quick(r,mod-2);
            int invl=quick(l,mod-2);
            //cout<<"-------"<<l<<" "<<r<<" "<<invl<<" "<<invr<<endl;
            f[i]=( 1ll*a+1ll*(r-l)*invr%mod*(num[i-1]-num[x-1]) )%mod*r%mod*invl;
            f[i]=f[i]%mod;
            num[i]=(num[i-1]+f[i])%mod;
            //cout<<f[i]<<endl;
        }
        while(q--){
            int l,r;
            l=io.xint();
            r=io.xint();
            printf("%lld\n",((num[r-1]-num[l-1])%mod+mod)%mod);
        }
    }
}
View Code

 2019 Multi-University Training Contest 8

Solved Pro.ID Title
  1001 Acesrc and Cube Hypernet
  1002 Acesrc and Girlfriend
  1003 Acesrc and Good Numbers
  1004 Acesrc and Hunting
  1005 Acesrc and String Theory
  1006 Acesrc and Travel
  1007 Andy and Data Structure
    1008 Andy and Maze
  1009 Calabash and Landlord
  1010 Quailty and CCPC
  1011 Roundgod and Milk Tea

1001

1002

1003

隊友補了

1004

思路:構造

代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
vector<pair<int,int>  > vs;
//map<pair<int,int>,int> mp;
int main(){
    int T; scanf("%d",&T);
    while(T--){
       int n,m; scanf("%d %d",&n,&m);
       if(n==1 && m==1) {
        printf("YES\n");
        printf("1 1\n");
       }
       else if(n==1 || m==1) printf("NO\n");
       else if(n==2  && m==2 ) printf("NO\n");
       else {
          printf("YES\n");
          vs.clear();
          //mp.clear();
          int flag=0;
          if(n>m) { swap(n,m); flag=1; }

          for(int i=1;i<=n;i+=2){
            if(n%2==1 && i+2==n){ // cout<<"----"<<endl;
                 int x=i;
                 int y=1;
                 while(y<=m){
                       if(m%2==1 && y+2==m){
                          vs.push_back({x,y});
                          vs.push_back({x+2,y+1});
                          vs.push_back({x+1,y+2});
                          vs.push_back({x,y+1});
                          vs.push_back({x+1,y});
                          vs.push_back({x+2,y+2});
                          vs.push_back({x,y+2});
                          vs.push_back({x+1,y+1});
                          vs.push_back({x+2,y});
                          break;
                       }
                       else {
                          vs.push_back({x,y});
                          vs.push_back({x+1,y+1});
                          vs.push_back({x+2,y});
                          vs.push_back({x,y+1});
                          vs.push_back({x+1,y});
                          vs.push_back({x+2,y+1});
                       }
                       y+=2;
                 }
                 break;
            }
            else {
                if(m==3){
                    int x=i;  int y=1;  vs.push_back({x,y});   vs.push_back({x+1,y+1}); vs.push_back({x,y+2});
                                        vs.push_back({x+1,y}); vs.push_back({x,y+1});     vs.push_back({x+1,y+2});
                }
                else  if(m%2==0){
                    int x=i;
                    int y=1;
                    while(y<=m) {vs.push_back({x,y}); y+=2; } y-=2;
                    x++; y++;    // printf("%d %d\n",x,y);
                    while(y>=1) { vs.push_back({x,y}); y-=2; } y+=2;
                    x--; y+=2;
                    while(y<=m) {vs.push_back({x,y}); y+=2; } y-=2;
                    x++; y--;
                    while(y>=1) { vs.push_back({x,y}); y-=2; } y+=2;
                    x--; y++;    vs.push_back({x,y});
                }
                else {
                    int x=i;
                    int y=1;
                    while(y<=m) { vs.push_back({x,y});y+=2; } y-=2;
                    x++; y--;
                    while(y>=1) { vs.push_back({x,y}); y-=2; } y+=2;
                    x--; y+=2;
                    while(y<=m) { vs.push_back({x,y}); y+=2; } y-=2;
                    x++; y++;
                    while(y>=1) { vs.push_back({x,y});y-=2; } y+=2;
                    x--; y++;     vs.push_back({x,y});
                }
            }
          }

          /*int kkk=0;

          for(int i=0;i<vs.size();i++){
             if(mp[vs[i]]) kkk=1;
             mp[vs[i]]++;
          }
          for(int i=1;i<vs.size();i++){
              int x=(vs[i].first-vs[i-1].first)*(vs[i].first-vs[i-1].first);
              int y=(vs[i].second-vs[i-1].second)*(vs[i].second-vs[i-1].second);
              double z=sqrt(1.00*x+1.00*y);
              if(z<=1 || z>=3) kkk=1;
          }*/


          if(flag){
               for(int i=0;i<vs.size();i++){
                  printf("%d %d\n",vs[i].second,vs[i].first);
               }
          }
          else{
              for(int i=0;i<vs.size();i++){
                printf("%d %d\n",vs[i].first,vs[i].second);
              }
          }
       }
    }
}
[ Copy to Clipboard ]    [ Save to File]
View Code

1005

1006

思路:樹形dp

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
const LL INF = 0x3f3f3f3f3f3f3f3f;
vector<int> g[N];
int a[N], b[N], n, u, v, T;
LL dp[N][2], d[N][2];
void dfs(int u, int o) {
    dp[u][1] = -INF;
    dp[u][0] = INF;
    for (int v : g[u]) {
        if(v != o) {
            dfs(v, u);
            dp[u][1] = max(dp[u][1], dp[v][0]+a[u]-b[u]);
            dp[u][0] = min(dp[u][0], dp[v][1]+a[u]-b[u]);
        }
    }
    if(dp[u][1] == -INF) dp[u][1] = a[u]-b[u];
    if(dp[u][0] == INF) dp[u][0] = a[u]-b[u];
}
void DFS(int u, int o) {
    LL mx1 = INF, mx2 = INF;
    int v1 = -1, v2 = -1;
    if(u == 1 && g[u].size() == 1) d[u][0] = d[u][1] = a[u]-b[u];
    for (int v : g[u]) {
        if(v != o) {
            if(dp[v][1]+a[u]-b[u] < mx1) {
                mx2 = mx1;
                v2 = v1;
                mx1 = dp[v][1]+a[u]-b[u];
                v1 = v;
            }
            else if(dp[v][1]+a[u]-b[u] == mx1 || dp[v][1]+a[u]-b[u] < mx2) {
                mx2 = dp[v][1]+a[u]-b[u];
                v2 = v;
            }
        }
    }
   // if(u != 1) {
        if(d[u][0] < mx1) {
            mx2 = mx1;
            v2 = v1;
            mx1 = d[u][0];
            v1 = -1;
        }
        else if(d[u][0] == mx1 || d[u][0] < mx2) {
            mx2 = d[u][0];
            v2 = -1;
        }
    //}
    for (int v : g[u]) {
        if(v != o) {
            if(v == v1) d[v][1] = max(d[v][1], mx2+a[v]-b[v]);
            else d[v][1] = max(d[v][1], mx1+a[v]-b[v]);
        }
    }

    ///
    mx1 = -INF, mx2 = -INF;
    v1 = -1, v2 = -1;
    for (int v : g[u]) {
        if(v != o) {
            if(dp[v][0]+a[u]-b[u] > mx1) {
                mx2 = mx1;
                v2 = v1;
                mx1 = dp[v][0]+a[u]-b[u];
                v1 = v;
            }
            else if(dp[v][0]+a[u]-b[u] == mx1 || dp[v][0]+a[u]-b[u] > mx2) {
                mx2 = dp[v][0]+a[u]-b[u];
                v2 = v;
            }
        }
    }
    //if(u != 1) {
        if(d[u][1] > mx1) {
            mx2 = mx1;
            v2 = v1;
            mx1 = d[u][1];
            v1 = -1;
        }
        else if(d[u][1] == mx1 || d[u][1] > mx2) {
            mx2 = d[u][1];
            v2 = -1;
        }
   // }
    for (int v : g[u]) {
        if(v != o) {
            if(v == v1) d[v][0] = min(d[v][0], mx2+a[v]-b[v]);
            else d[v][0] = min(d[v][0], mx1+a[v]-b[v]);
        }
    }

    for (int v : g[u]) {
        if(v != o) {
            DFS(v, u);
        }
    }
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
        for (int i = 1; i < n; ++i) {
            scanf("%d %d", &u, &v);
            g[u].pb(v);
            g[v].pb(u);
        }
        dfs(1, 1);
        for (int i = 1; i <= n; ++i) d[i][0] = INF, d[i][1] = -INF;
        DFS(1, 1);
        LL ans = -INF;
        for (int i = 1; i <= n; ++i) {
            if(i == 1) ans = max(ans, dp[i][0]);
            else if(g[i].size() == 1) ans = max(ans, d[i][0]);
            else ans = max(ans, min(dp[i][0], d[i][0]));
           //cout << i << " " << dp[i][0] << " " << d[i][0] << endl;
        }
        printf("%lld\n", ans);
        for (int i = 1; i <= n; ++i) g[i].clear();
    }
    return 0;
}
View Code

1007

1008

隊友補了

1009

思路:坐標離散化+狀壓+搜索

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

int T, x1[5], y1[5], x2[5], y2[5];
vector<int> vx, vy;
int c[10][10];
bool vis[10][10];
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
void dfs(int x, int y) {
    vis[x][y] = true;
    for (int j = 0; j < 4; ++j) {
        int xx = x + dir[j][0];
        int yy = y + dir[j][1];
        if(1 <= xx && xx < vx.size() && 1 <= yy && yy < vy.size() && !vis[xx][yy] && c[xx][yy] == c[x][y]) {
            dfs(xx, yy);
        }
    }
}
int main() {
    scanf("%d", &T);
    while(T--) {
        vx.clear();
        vy.clear();
        for (int i = 1; i <= 2; ++i) {
            scanf("%d %d %d %d", &x1[i], &y1[i], &x2[i], &y2[i]);
            vx.pb(x1[i]), vx.pb(x2[i]);
            vy.pb(y1[i]), vy.pb(y2[i]);
        }
        vx.pb(-1), vx.pb(1e9 + 7);
        vy.pb(-1), vy.pb(1e9 + 7);
        sort(vx.begin(), vx.end());
        vx.erase(unique(vx.begin(), vx.end()), vx.end());
        sort(vy.begin(), vy.end());
        vy.erase(unique(vy.begin(), vy.end()), vy.end());
        for (int i = 1; i < vx.size(); ++i) {
            for (int j = 1; j < vy.size(); ++j) {
                int x = vx[i-1], y = vy[j-1];
                int xx = vx[i], yy = vy[j];
                int st = 0;
                for (int k = 1; k <= 2; ++k) {
                    if(x >= x1[k] && y >= y1[k] && xx <= x2[k] && yy <= y2[k]) st |= 1<<k;
                }
                c[i][j] = st;
            }
        }
        for (int i = 1; i <= 7; ++i) for (int j = 1; j <= 7; ++j) vis[i][j] = false;
        int ans = 0;
        for (int i = 1; i < vx.size(); ++i) {
            for (int j = 1; j < vy.size(); ++j) {
                if(!vis[i][j]) {
                    dfs(i, j);
                    ans++;
                   // cout << i << " " << j << endl;
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

1010

思路:模擬

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/

            const int maxn = 1e5+9;
            struct node{
                char str[15];
                int p, t;
            }a[maxn];
            bool cmp(node a, node b) {
                if(a.p == b.p) {
                    return a.t < b.t;
                }
                return a.p > b.p;
            }
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                int n,d;
                scanf("%d%d", &n, &d);
                for(int i=1; i<=n; i++) {
                    scanf("%s%d%d", a[i].str, &a[i].p, &a[i].t);
                }
                if(n * d % 10 == 5) {
                    sort(a+1, a+1+n, cmp);
                    int up = n * d / 10 + 1;
                    printf("%s\n", a[up].str);
                }
                else puts("Quailty is very great");
            }
            return 0;
}
View Code

1011

思路:貪心

代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int a[maxn];
int b[maxn];
int main(){
    int T; scanf("%d",&T);
    while(T--){
        int n; scanf("%d",&n);
        long long tot=0;
        for(int i=1;i<=n;i++) {
            scanf("%d %d",&a[i],&b[i]);
            tot+=b[i];
        }
        long long ans=0;
        for(int i=1;i<=n;i++){
            long long c=min(tot-max(1ll*0,1ll*b[i]-ans)-ans,1ll*a[i]);
            if(c>0) ans+=c;
        }
        printf("%lld\n",ans);
    }
}
View Code

  2019 Multi-University Training Contest 9

Solved Pro.ID Title
  1001 Rikka with Quicksort
  1002 Rikka with Cake
  1003 Rikka with Mista
  1004 Rikka with Geometric Sequence
  1005 Rikka with Game
  1006 Rikka with Coin
  1007 Rikka with Travels
    1008 Rikka with Stable Marriage
  1009 Rikka with Traffic Light
  1010 Rikka with Defensive Line
  1011 Rikka with Segment Tree

1001

1002

思路:切成的塊等於交點個數加一。

代碼:

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/
            const int maxn = 1e5+9;
//            vector<pii>node;
            struct node{
                int x, y;
                int tp;
            } a[maxn];

            vector<int>vec;
            inline int getid(int x) {
                return lower_bound(vec.begin(), vec.end(), x) - vec.begin();
            }
            char op[5];
            bool cmp(node a, node b){
                return a. y > b.y;
            }
            struct Tree{
                int N;
                int sum[maxn];
                void init(int n) {
                    N = n;
                    for (int i = 0; i <= N; ++i) sum[i] = 0;
                }
                int lowbit(int x) {
                    return x & (-x);
                }
                void update(int pos, int val) {
                    while(pos <= N) {
                        sum[pos] += val;
                        pos += lowbit(pos);
                    }
                }
                int query(int pos) {
                    int res = 0;
                    while(pos > 0) {
                        res += sum[pos];
                        pos -= lowbit(pos);
                    }
                    return res;
                }
            } Le, Ri;


int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                int n,m,k;

                scanf("%d%d%d", &n, &m, &k);
                vec.clear();
                vec.pb(0);
                vec.pb(n);
                for(int i=1; i<=k; i++) {
                    int x, y;
                    scanf("%d%d%s", &x, &y, op);
                    a[i].x = x, a[i].y = y;
                    if(op[0] == 'U') a[i].tp = 0;
                    else if(op[0] == 'L') a[i].tp = 1;
                    else if(op[0] == 'D') a[i].tp = 2;
                    else a[i].tp = 3;
                    vec.pb(x);
                }
                sort(vec.begin(), vec.end());
                vec.erase(unique(vec.begin(), vec.end()), vec.end());

                sort(a+1, a+1+k, cmp);

                Le.init(getid(n));
                Ri.init(getid(n));
                ll sum = 0;
                for(int i=1; i<=k; i++) {
                    if(a[i].tp == 2) continue;
                    if(a[i].tp == 1) {
                        Le.update(getid(a[i].x), 1);
                    }
                    else if(a[i].tp == 3) {
                        Ri.update(getid(a[i].x), 1);
                    }
                    else {
                        sum += Le.query(getid(n)) - Le.query(getid(a[i].x));
                        sum += Ri.query(getid(a[i].x));
                    }
                }

                Le.init(getid(n));
                Ri.init(getid(n));
                for(int i=k; i>=1; i--) {
                    if(a[i].tp == 0) continue;
                    if(a[i].tp == 1) {
                        Le.update(getid(a[i].x), 1);
                    }
                    else if(a[i].tp == 3) {
                        Ri.update(getid(a[i].x), 1);
                    }
                    else {
                        sum += Le.query(getid(n)) - Le.query(getid(a[i].x));
                        sum += Ri.query(getid(a[i].x));
                    }
                }
                printf("%lld\n", sum + 1);
            }
            return 0;
}
View Code

1003

思路:桶排序+雙指針。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
#define ll long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 55, M = 1.2e6 + 10;
int a[N], T, n, p[10];
vector<int> vc[10], vv[10], t[10];
int pos[10], l[M], r[M];
int main() {
    p[0] = 1;
    for (int i = 1; i < 10; ++i) p[i] = p[i-1]*10;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 0; i < n; ++i) scanf("%d", &a[i]);
        int y = n/2, x = n-y;
        int upx = 1<<x, upy = 1<<y;
        for (int i = 0; i < upx; ++i) {
            int tot = 0;
            for (int j = 0; j < x; ++j) if(i&(1<<j)) tot += a[j];
            vc[0].pb(tot);
        }
        for (int i = 0; i < upy; ++i) {
            int tot = 0;
            for (int j = 0; j < y; ++j) if(i&(1<<j)) tot += a[j+x];
            vv[0].pb(tot);
        }

        for (int i = 1; i <= 9; ++i) {
            for (int x : vc[i-1]) t[x/p[i-1]%10].pb(x);
            for (int j = 0; j < 10; ++j) {
                for (int x : t[j]) vc[i].pb(x);
                t[j].clear();
            }
        }
        for (int i = 1; i <= 9; ++i) for (int &x : vc[i]) x %= p[i];

        for (int i = 1; i <= 9; ++i) {
            for (int x : vv[i-1]) t[x/p[i-1]%10].pb(x);
            for (int j = 0; j < 10; ++j) {
                for (int x : t[j]) vv[i].pb(x);
                t[j].clear();
            }
        }
        for (int i = 1; i <= 9; ++i) for (int &x : vv[i]) x %= p[i];
        LL ans = 0;
        for (int i = 1; i < 10; ++i) {
            int p1 = 0, sz = upy, L = 4*p[i-1], R = 5*p[i-1]-1;
            int j = upx-1;
            for (; j >= 0; --j) {
                int x = vc[i][j];
                if(x <= R) break;
                while(p1 < sz && vv[i][p1]+x <= p[i] + R) ++p1;
                r[j] = p1;
            }
            p1 = 0;
            for (; j >= 0; --j) {
                int x = vc[i][j];
                while(p1 < sz && vv[i][p1]+x <= R) ++p1;
                r[j] = p1;
            }
            p1 = 0;
            j = upx-1;
            for (; j >= 0; --j) {
                int x = vc[i][j];
                if(x < L) break;
                while(p1 < sz && vv[i][p1]+x < p[i] + L) ++p1;
                l[j] = p1;
            }
            p1 = 0;
            for (; j >= 0; --j) {
                int x = vc[i][j];
                while(p1 < sz && vv[i][p1]+x < L) ++p1;
                l[j] = p1;
            }
            for (int j = 0; j < upx; ++j) {
                if(l[j] <= r[j]) ans += r[j]-l[j];
                else ans += sz+r[j]-l[j];
            }
        }
        printf("%lld\n", ans);
        for (int i = 0; i < 10; ++i) vc[i].clear(), vv[i].clear();
    }
    return 0;
View Code

1004

1005

思路:特判$"z*"$,$"yyyyz*"$這兩種情況,將z改成b

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define double long double
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

int T;
string s;
int main() {
    fio;
    cin >> T;
    while(T--) {
        cin >> s;
        if(s[0] == 'z') s[0] = 'b';
        else {
            for (int j = 0; j < s.size(); ++j) {
                if(s[j] != 'y') {
                    if(s[j] == 'z') s[j] = 'b';
                    break;
                }
            }
        }
        cout << s << endl;
    }
    return 0;
}
View Code

1006

思路:我們發現10的個數不會超過2,20的個數不會超過10,50的個數不會超過2。然后預處理對於這三個硬幣不同的個數能組成的面值,最后暴力判斷100所需的個數。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define double long double
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 105;
int T, n, a[N];
vector<int> vc[3][11][3];
int main() {
    scanf("%d", &T);
    for (int i = 0; i <= 2; ++i) {
        for (int j = 0; j <= 10; ++j) {
            for (int k = 0; k <= 2; ++k) {
                for (int ii = 0; ii <= i; ++ii) {
                    for (int jj = 0; jj <= j; ++jj) {
                        for (int kk = 0; kk <= k; ++kk) {
                            vc[i][j][k].pb(ii*10+jj*20+kk*50);
                        }
                    }
                }
                sort(vc[i][j][k].begin(), vc[i][j][k].end());
            }
        }
    }
    while(T--) {
        scanf("%d", &n);
        bool f = false;
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            if(a[i]%10) f = true;
        }
        if(f) {
            printf("-1\n");
            continue;
        }
        int ans = 1e9 + 10;
        for (int i = 0; i <= 2; ++i) {
            for (int j = 0; j <= 10; ++j) {
                for (int k = 0; k <= 2; ++k) {
                    bool ok = true;
                    int mx = 0;
                    for (int l = 1; l <= n; ++l) {
                        int t = min(a[l], a[l]%100+300);
                        bool f = false;
                        for (; t >= 0; t -= 100) {
                            auto tt = lower_bound(vc[i][j][k].begin(), vc[i][j][k].end(), t);
                            if(tt != vc[i][j][k].end() && (*tt) == t) {
                                f = true;
                                mx = max(mx, (a[l]-t)/100);
                                break;
                            }
                        }
                        if(!f) {
                            ok = false;
                            break;
                        }
                    }
                    if(!ok) continue;
                    ans = min(ans, i+j+k+mx);
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

1007

思路:直徑上的端點一定會被用到,先把直徑扣出來,然后在直徑上求個前綴最大值和后綴最大值,在求出以直徑上每個點為根的小樹的中最長鏈。

代碼:

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/
            const int maxn = 1e5+9;
            int n;
            vector<int>mp[maxn];
            int vis[maxn];
            int dis[maxn];
            vector<int>lian;
            ///扣出最長鏈
            void koulian() {
                for(int i=1; i<=n; i++) dis[i] = inf;
                dis[1] = 0;
                queue<int>que;  que.push(1);
                int t = 1;
                while(!que.empty()) {
                    int u = que.front(); que.pop();
                    if(dis[u] > dis[t])t = u;
                    for(int v : mp[u]) {
                        if(dis[v] > dis[u] + 1) {
                            dis[v] = dis[u] + 1;
                            que.push(v);
                        }
                    }
                }

                for(int i=1; i<=n; i++) dis[i] = inf;
                dis[t] = 0;
                que.push(t);
                int s = t;
                while(!que.empty()) {
                    int u = que.front(); que.pop();
                    if(dis[u] > dis[s])s = u;
                    for(int v:mp[u]) {
                        if(dis[v] > dis[u] + 1) {
                            dis[v] = dis[u] + 1;
                            que.push(v);
                        }
                    }
                }
                lian.pb(s);
                vis[s] = 1;
                while(s != t) {
                    for(int v : mp[s]) {
                        if(dis[v] +1 == dis[s]) {
                            s = v;
                            lian.pb(s);
                            vis[s] = 1;
                            break;
                        }
                    }
                }
            }

            int dpa[maxn], dpb[maxn][2], pre[maxn];
            int dppre[maxn], dpback[maxn];
            ///求出以最長鏈上一個點為根節點的不經過最長鏈的最大深度
            void dfs1(int u, int fa) {
                dpa[u] = 1;
                for(int v : mp[u]) {
                    if(v == fa || vis[v]) continue;
                    dfs1(v, u);
                    dpa[u] = max(dpa[u], dpa[v] + 1);
                }}
            void dfs2(int u, int fa) {
                dpb[u][0] = dpb[u][1] = 1;
                ///dpb[0]表示包含根節點的最長鏈
                ///dpb[1]表示包含根節點的次長鏈
                pre[u] = 1;
                for(int v : mp[u]) {
                    if(vis[v] || v == fa) continue;
                    dfs2(v, u);
                    pre[u] = max(pre[u], pre[v]);

                    if(dpb[u][1] <= dpb[v][0] + 1){
                        dpb[u][1] = dpb[v][0] + 1;
                        if(dpb[u][0] < dpb[u][1]) {
                            swap(dpb[u][0], dpb[u][1]);
                        }
                    }
                }
                pre[u] = max(pre[u], dpb[u][0] + dpb[u][1] - 1);
            }
            int hei[maxn];
int main(){
            int T;  scanf("%d", &T);
            while(T--){
                scanf("%d", &n);
                for(int i=1; i<n; i++) {
                    int u, v;
                    scanf("%d%d", &u, &v);
                    mp[u].pb(v);
                    mp[v].pb(u);
                }
                for(int i=0; i<=n; i++) vis[i] = 0, hei[i] = 0, pre[i] = 0, dppre[i] = 0,dpback[i] = 0;

                koulian();
                for(int i=0; i<lian.size(); i++) {
                    int v = lian[i];
                    dfs1(v, v);
                    if(i)dppre[i] =  max(dppre[i-1], dpa[v] + i);
                    else dppre[i] = dpa[v];
                    for(int p : mp[v]) {
                        if(vis[p]) continue;
                        dfs2(p, p);
                        pre[v] = max(pre[v], pre[p]);
                    }
                    pre[v] = max(pre[v], pre[lian[max(0, i-1)]]);
                }
                int cc = 0;
                for(int i=lian.size()-1; i>=0; i--) {
                    if(i == lian.size() - 1) dpback[i] = dpa[lian[i]];
                    else dpback[i] = max(dpback[i+1], dpa[lian[i]] + cc);
                    cc++;
                }
                int all = lian.size();
                hei[all] = pre[lian[all-1]];
                hei[pre[lian[all-1]]] = all;

                for(int i=lian.size() - 1; i>=1; i--) {
                    int v = lian[i];
                    int a = dppre[i-1];
                    int b = dpback[i];
                    hei[a] = max(hei[a], b);
                    hei[b] = max(hei[b], a);
                }
                ll sum = 0;
                int c = 0;

                for(int i=all; i>=1; i--) {
                    c = max(c, hei[i]);
                    sum = sum + c;
                }
                printf("%lld\n", sum);
                lian.clear();
                for(int i=1; i<=n; i++) mp[i].clear();
            }
            return 0;
}
View Code

1008

思路:貪心,從最高位開始,每一位盡可能不同。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
int a[N], b[N], n, T;
vector<int> vc;
struct Trie {
    int trie[N*30][2], cnt[N*30], tot;
    inline void clr() {
        for (int i = 0; i <= tot; ++i) trie[i][0] = trie[i][1] = cnt[i] = 0;
        tot = 0;
    }
    inline void ins(int x) {
        int rt = 0;
        for (int i = 29; i >= 0; --i) {
            int id = (x>>i)&1;
            if(!trie[rt][id]) trie[rt][id] = ++tot;
            rt = trie[rt][id];
            cnt[rt]++;
        }
    }
}A, B;
inline int solve() {
    int ra = 0, rb = 0, res = 0;
    for (int i = 29; i >= 0; --i) {
        if(A.cnt[A.trie[ra][0]] && B.cnt[B.trie[rb][1]]) {
            ra = A.trie[ra][0];
            rb = B.trie[rb][1];
            A.cnt[ra]--;
            B.cnt[rb]--;
            res |= 1<<i;
        }
        else if(A.cnt[A.trie[ra][1]] && B.cnt[B.trie[rb][0]]) {
            ra = A.trie[ra][1];
            rb = B.trie[rb][0];
            A.cnt[ra]--;
            B.cnt[rb]--;
            res |= 1<<i;
        }
        else if(A.cnt[A.trie[ra][0]] && B.cnt[B.trie[rb][0]]){
            ra = A.trie[ra][0];
            rb = B.trie[rb][0];
            A.cnt[ra]--;
            B.cnt[rb]--;
            
        }
        else {
            ra = A.trie[ra][1];
            rb = B.trie[rb][1];
            A.cnt[ra]--;
            B.cnt[rb]--;
        }
    }
    return res;
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        A.clr(), B.clr();
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), A.ins(a[i]);
        for (int i = 1; i <= n; ++i) scanf("%d", &b[i]), B.ins(b[i]);
        LL ans = 0;
        for (int i = 1; i <= n; ++i) ans += solve();
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

1009

1010

1011

 2019 Multi-University Training Contest 10

Solved Pro.ID Title
  1001 Minimum Spanning Trees
  1002 Line Graphs
  1003 Valentine's Day
  1004 Play Games with Rounddog
  1005 Welcome Party
  1006 Dense Subgraph
  1007 Closest Pair of Segments
  1008 Coins
  1009 Block Breaker
  1010 Domino Covering
  1011 Make Rounddog Happy

1001

1002

1003

思路:如果有一個大於0.5,那么答案就是最大值,否則就是最大的幾個合並的概率,這個可以暴力算。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
#define ll long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e4 + 10;
int T, n, a[N];
char s[15];
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%s", s);
            a[i] = 0;
            for (int j = 0; j < 8; ++j) {
                if(s[j] == '.') continue;
                a[i] = a[i]*10+s[j]-'0';
            }
        }
        sort(a+1, a+1+n);
        double ans;
        if(a[n] >= 500000) {
            ans = a[n]*1./1000000.;
        }
        else {
            ans = a[n]*1./1000000.;
            double tmp = ans, p = (1000000.-a[n])/1000000.;
            for (int i = n-1; i >= 1; --i) {
                tmp = (tmp*(1000000.-a[i]) + a[i]*p)/1000000.;
                p *= (1000000.-a[i])/1000000.;
                ans = max(ans, tmp);
            }
        }
        printf("%.10f\n", ans);
    }
    return 0;
}
View Code

1004

1005

思路:隊友寫的

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <bits/stdc++.h>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/

            const int maxn = 1e5+9;
            pll a[maxn];
            multiset<ll>st;
            bool cmp(pll a, pll b) {
                if(a.fi == b.fi) {
                    return a.se < b.se;
                }
                return a.fi > b.fi;
            }
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                st.clear();
                int n;  scanf("%d", &n);
                for(int i=1; i<=n; i++) {
                    scanf("%lld%lld", &a[i].fi, &a[i].se);
                }
                sort( a+1, a+1+n, cmp);
                ll premax = -inff;
                ll ans = inff;
                for(int i=n; i>=1; i--) st.insert(a[i].se);
                for(int i=1; i<=n; i++) {
                    st.erase(st.find(a[i].se));
                    ans = min(ans, abs(premax - a[i].fi));

//                    if(premax < a[i].fi) {
                        auto it = st.lower_bound(a[i].fi);
                        if(it != st.end() && (*it )> premax) {
                            ans = min(ans, abs(*it - a[i].fi));
                        }
                        if(it != st.begin()) {
                            it--;
                            if((*it > premax)) {
                                ans = min(ans, abs(*it - a[i].fi));
                            }
                        }
//                    }
                    premax = max(premax, a[i].se);
                }
                printf("%lld\n", ans);
            }
            return 0;
}
View Code

1006

1007

思路:先按x坐標排序,然后$O(n^2)$暴力枚舉,再剪一下枝。

代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=10000+10;
const double pi=acos(-1);
struct Point{
    double x,y;
    Point(){ x=0,y=0; }
    Point(double _x,double _y):x(_x),y(_y){}
    Point operator -(const Point &b)const {     return Point(x-b.x,y-b.y);}
};
double dis(Point A,Point B)             { return sqrt( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
inline double cross(Point a,Point b)    {   return a.x*b.y-a.y*b.x;                             } //叉積
inline double dot(Point a,Point b)      {   return a.x*b.x+a.y*b.y;                             } //點積
struct node{ Point a,b,c; }pa[maxn];
bool up(node pa,node pb){
    if(pa.c.x==pb.c.x) return pa.c.y<pb.c.y;
                       return pa.c.x<pb.c.x;
}
double make(Point a,Point b,Point c){
    double ans=1e18;
    double area=cross(a-c,b-c)/dis(a,b); area=fabs(area);
    //cout<<area<<endl;
    if(dot(a-b,c-b)<0) return ans;
    if(dot(b-a,c-a)<0) return ans;
    return area;
}
double work(node pa,node pb){
    double ans=1e18;
    ans=min(ans,dis(pa.a,pb.a));
    ans=min(ans,dis(pa.a,pb.b));
    ans=min(ans,dis(pa.b,pb.a));
    ans=min(ans,dis(pa.b,pb.b));
    ans=min(ans,make(pa.a,pa.b,pb.a));
    ans=min(ans,make(pa.a,pa.b,pb.b));
    ans=min(ans,make(pb.a,pb.b,pa.a));
    ans=min(ans,make(pb.a,pb.b,pa.b));
    return ans;
}
int main(){

   // cout<<dot(Point{1,1},Point{-1,0})<<endl;
    int T; scanf("%d",&T);
    while(T--){
        int n; scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%lf %lf %lf %lf",&pa[i].a.x,&pa[i].a.y,&pa[i].b.x,&pa[i].b.y);
            pa[i].c.x=min(pa[i].a.x,pa[i].b.x);
            pa[i].c.y=min(pa[i].a.y,pa[i].b.y);
        }
        sort(pa+1,pa+1+n,up);
        double ans=1e18;
        for(int i=1;i<=n;i++){
            double r=max(pa[i].a.x,pa[i].b.x);
            for(int j=i+1;j<=n;j++){
                double l=min(pa[j].a.x,pa[j].b.x);
                if(l-r>ans) break;
                ans=min(ans,work(pa[i],pa[j]));
            }
        }
        printf("%.10f\n",ans);
    }
}
View Code

1008

1009

思路:隊友寫的

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/

            const int maxn = 2009;
            int mp[maxn][maxn];
            queue<pii>que;
            int nx[4][2]  ={{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                int n,m,q;
                scanf("%d%d%d", &n, &m, &q);
                for(int i=0; i<=n+1; i++) {
                    for(int j=0; j<=m+1; j++) {
                        mp[i][j] = 1;
                    }
                }
                while(q--) {
                    int x, y;
                    int cnt = 0;
                    scanf("%d%d", &x, &y);
                    if(mp[x][y] == 0) puts("0");
                    else {
                        while(!que.empty()) que.pop();
                        cnt = 1;
                        mp[x][y] = 0;
                        que.push(pii(x, y));
                        while(!que.empty()) {
                            pii f = que.front(); que.pop();
                            int cx = f.fi, cy = f.se;
                            for(int i=0; i<4; i++) {
                                int tx = cx + nx[i][0];
                                int ty = cy + nx[i][1];
                                if(tx < 1 || tx > n || ty < 1 || ty > m) continue;
                                if(mp[tx][ty] == 0) continue;
                                if(mp[tx-1][ty] == 0 || mp[tx+1][ty] == 0) {
                                    if(mp[tx][ty-1] == 0||mp[tx][ty+1] == 0) {
                                        cnt++;
                                        mp[tx][ty] = 0;
                                        que.push(pii(tx, ty));
                                    }
                                }
                            }
                        }
                        printf("%d\n", cnt);
                    }
                }
            }
            return 0;
}
View Code

1010

1011

思路:用單調棧求出以每個位置為最大值區間的左端點和右端點。由於還要保證每個數只出現一次,所以還要處理出每個位置往左往右不重復能到達的位置。最后再用啟發式暴力枚舉。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
#define ll long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 3e5 + 5;
int a[N], n, k, T, L[N], R[N], p[N], nxt[N], pre[N], mx[N], mn[N];
stack<int> st;
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &k);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        a[0] = a[n+1]  = n+1;
        while(!st.empty()) st.pop();
        st.push(0);
        for (int i = 1; i <= n; ++i) {
            while(!st.empty() && a[st.top()] <= a[i]) st.pop();
            L[i] = st.top()+1;
            st.push(i);
        }

        while(!st.empty()) st.pop();
        st.push(n+1);
        for (int i = n; i >= 1; --i) {
            while(!st.empty() && a[st.top()] <= a[i]) st.pop();
            R[i] = st.top()-1;
            st.push(i);
        }
        for (int i = 1; i <= n; ++i) p[i] = n+1;
        for (int i = n; i >= 1; --i) {
            nxt[i] = p[a[i]];
            p[a[i]] = i;
        }
        for (int i = 1; i <= n; ++i) p[i] = 0;
        for (int i = 1; i <= n; ++i) {
            pre[i] = p[a[i]];
            p[a[i]] = i;
        }
        mx[n] = n;
        for (int i = n-1; i >= 1; --i) {
            mx[i] = min(mx[i+1], nxt[i]-1);
        }
        mn[1] = 1;
        for (int i = 2; i <= n; ++i) {
            mn[i] = max(mn[i-1], pre[i]+1);
        }
        LL ans = 0;
        for (int i = 1; i <= n; ++i) {
            int len = max(1, a[i]-k);
            if(i-L[i] <= R[i]-i) {
                for (int j = L[i]; j <= i; ++j) {
                    int r = min(R[i], mx[j]);
                    if(r >= i && r-j+1 >= len) {
                        ans += min(r-j+1-len+1, r-i+1);
                    }
                }
            }
            else {
                for (int j = i; j <= R[i]; ++j) {
                    int l = max(L[i], mn[j]);
                    if(l <= i && j-l+1 >= len) {
                        ans += min(j-l+1-len+1, i-l+1);
                    }
                }
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM