暑期多校

时间:2024-03-01 15:30:02

咕值详见去年多校

牛客

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