• 2019 Multi-University Training Contest 3


    http://acm.hdu.edu.cn/showproblem.php?pid=6604

    Problem Description

    Country A and B are at war. Country A needs to organize transport teams to deliver supplies toward some command center cities.

    In order to ensure the delivery works efficiently, all the roads in country A work only one direction. Therefore, map of country A can be regarded as DAG( Directed Acyclic Graph ). Command center cities only received supplies and not send out supplies.

    Intelligence agency of country B is credibly informed that there will be two cities carrying out a critical transporting task in country A. 

    As long as **any** one of the two cities can not reach a command center city, the mission fails and country B will hold an enormous advantage. Therefore, country B plans to destroy one of the n cities in country A and all the roads directly connected. (If a city carrying out the task is also a command center city, it is possible to destroy the city to make the mission fail)

    Now country B has made q hypotheses about the two cities carrying out the critical task.
    Calculate the number of plan that makes the mission of country A fail.

    Input

    The first line contains a integer T (1T10), denoting the number of test cases.

    In each test case, the first line are two integers n,m, denoting the number of cities and roads(1n100,000,1m200,000).
    Then m lines follow, each with two integers u and v, which means there is a directed road from city u to v (1u,vn,uv).

    The next line is a integer q, denoting the number of queries (1q100,000)
    And then q lines follow, each with two integers a and b, which means the two cities carrying out the critical task are a and b (1a,bn,ab).

    A city is a command center if and only if there is no road from it (its out degree is zero).

    Output

    For each query output a line with one integer, means the number of plan that makes the mission of country A fail.

    Sample Input

    2
    8 8
    1 2
    3 4
    3 5
    4 6
    4 7
    5 7
    6 8
    7 8
    2
    1 3
    6 7
    3 2
    3 1
    3 2
    2
    1 2
    3 1

    Sample Output

    4
    3
    2
    2
    

      

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn=2e5+10;
    int n,m,tim,dfn[maxn],repos[maxn],idom[maxn],fa[maxn],mi[maxn],f[maxn],semi[maxn],id[maxn],ans[maxn];
    int d[maxn],lc[maxn][25],w[maxn],T=24;
    
    struct edge {
        int tot, head[maxn], next[maxn], to[maxn];
    
        void clear() {
            tot = 0;
            for (int i = 0; i <= n; i++)
                head[i] = 0;
        }
        void add(int u, int v) {
            to[++tot] = v;
            next[tot] = head[u];
            head[u] = tot;
        }
    }G,RG,NG,TR;
    
    void init(){
        tim=0;
        G.clear();RG.clear();NG.clear();TR.clear();
        memset(lc,0, sizeof(lc));
        for (int i=1;i<=n;i++){
            repos[i]=dfn[i]=idom[i]=fa[i]=ans[i]=0;
            mi[i]=semi[i]=f[i]=i;
            w[i]=0;
        }
    }
    void dfs1(int x) {
        dfn[x] = ++tim;
        repos[tim] = x;
        for (int i = G.head[x]; i; i = G.next[i])
            if (!dfn[G.to[i]]) {
                fa[G.to[i]] = x;
                dfs1(G.to[i]);
            }
    }
    
    int find(int x) {
        if (x == f[x]) return x;
        int tmp = f[x];
        f[x] = find(f[x]);
        if (dfn[semi[mi[tmp]]] < dfn[semi[mi[x]]])
            mi[x] = mi[tmp];
        return f[x];
    }
    
    void dfs(int x) {
        for (int i = TR.head[x]; i; i = TR.next[i]) {
            int to = TR.to[i];
            d[to] = d[x] + 1;
            lc[to][0] = x;
            ans[to] += ans[x] + 1;//记录虚点到该点的支配点个数
            for (int j = 1;j<=T; j++)
                lc[to][j] = lc[lc[to][j - 1]][j - 1];
            dfs(to);
        }
    }
    
    int lca(int x,int y) {
        if (d[x] > d[y]) swap(x, y);
        for (int i = T; i >= 0; i--) {
            if (d[lc[y][i]] >= d[x])
                y = lc[y][i];
        }
        if (x == y) return x;
        for (int i = T; i >= 0; i--) {
            if (lc[x][i] != lc[y][i]) {
                x = lc[x][i];
                y = lc[y][i];
            }
        }
        return lc[x][0];
    }
    void work() {
        for (int i = n; i >= 2; i--) {
            int x = repos[i], tmp = n;
            for (int j = RG.head[x]; j; j = RG.next[j]) {
                if (!dfn[RG.to[j]]) continue;
                if (dfn[RG.to[j]] < dfn[x]) tmp = min(tmp, dfn[RG.to[j]]);
                else {
                    find(RG.to[j]);
                    tmp = min(tmp, dfn[semi[mi[RG.to[j]]]]);
                }
            }
            semi[x] = repos[tmp];
            f[x] = fa[x];
            NG.add(semi[x], x);
            x = repos[i - 1];
            for (int j = NG.head[x]; j; j = NG.next[j]) {
                int y = NG.to[j];
                find(y);
                if (semi[mi[y]] == semi[y]) idom[y] = semi[y]; else idom[y] = mi[y];
            }
        }
        for (int i = 2; i <= n; i++) {
            int x = repos[i];
            if (idom[x] != semi[x]) idom[x] = idom[idom[x]];
            TR.add(idom[x], x);
        }
        d[1]=1;
        dfs(1);
    }
    
    
    int main() {
        int _;
        scanf("%d", &_);
        while (_--) {
            scanf("%d%d", &n, &m);
            n++;
            init();
            for (int i = 1, v, u; i <= m; i++) {
                scanf("%d%d",&u, &v);
                u++;v++;
                swap(u, v);
                w[v]++;
                G.add(u, v);
                RG.add(v, u);
            }
            for (int i = 2; i <= n; i++) {
                if (!w[i]) {
                    G.add(1,i);
                    RG.add(i,1);
                }
            }
            dfs1(1);
    
            work();
            int q, x, y;
            scanf("%d", &q);
            while (q--) {
                scanf("%d%d", &x, &y);
                x++;
                y++;
                printf("%d
    ", ans[x] + ans[y] - ans[lca(x, y)]);
            }
        }
        return 0;
    } 

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int S=8;
    
    ll mult_mod(ll a,ll b,ll c)
    {
        a%=c;
        b%=c;
        ll ret=0,tmp=a;
        while (b)
        {
            if (b&1)
            {
                ret+=tmp;
                if (ret>c)
                {
                    ret-=c;
                }
            }
            tmp<<=1;
            if (tmp>c) tmp-=c;
            b>>=1;
        }
        return ret;
    }
    
    ll pow_mod(ll a,ll n,ll mod)
    {
        ll ret=1;
        ll temp=a%mod;
        while (n)
        {
            if(n&1)
            {
                ret=mult_mod(ret,temp,mod);
            }
            temp=mult_mod(temp,temp,mod);
            n>>=1;
        }
        return ret;
    }
    
    bool check(ll a,ll n,ll x,ll t)
    {
        ll ret=pow_mod(a,x,n);
        ll last=ret;
        for (int i=1; i<=t; i++)
        {
            ret=mult_mod(ret,ret,n);
            if (ret==1&&last!=1&&last!=n-1)
            {
                return 1;
            }
            last=ret;
        }
        if (ret!=1)
        {
            return 1;
        }
        return 0;
    }
    
    bool Miller_Rabin(ll n)
    {
        if (n<2)
        {
            return 0;
        }
        if (n==2)
        {
            return 1;
        }
        if ((n&1)==0)
        {
            return 0;
        }
        ll x=n-1;
        ll t=0;
        while ((x&1)==0)
        {
            x>>=1;
            t++;
        }
        srand(time(NULL));
        for (int i=0; i<S; i++)
        {
            ll a=rand()%(n-1)+1;
            if (check(a,n,x,t))
            {
                return 0;
            }
        }
        return 1;
    }
    
    ll factor[100];
    int tol;
    
    ll gcd(ll a,ll b)
    {
        if (!b)
        {
            return a;
        }
        return gcd(b,a%b);
    }
    ll pollard_rho(ll x,ll c)
    {
        ll i=1,k=2;
        srand(time(NULL));
        ll x0=rand()%(x-1)+1;
        ll y=x0;
        while (1)
        {
            i++;
            x0=(mult_mod(x0,x0,x)+c)%x;
            ll d=gcd(y-x0,x);
            if (d!=1&&d!=x)
            {
                return d;
            }
            if (y==x0)
            {
                return x;
            }
            if (i==k)
            {
                y=x0;
                k+=k;
            }
        }
    }
    
    __int128 quick(__int128 a,__int128 b,__int128 p)
    {
        __int128 ret=1%p;
        while (b)
        {
            if (b&1)
            {
                ret=ret*a%p;
            }
            b>>=1;
            a=a*a%p;
        }
        return ret;
    }
    
    void findfac(ll n,ll k)
    {
        if (n==1)
        {
            return;
        }
        if (Miller_Rabin(n))
        {
            factor[tol++]=n;
            return;
        }
        ll p=n;
        ll c=k;
        while (p>=n)
        {
            p=pollard_rho(p,c--);
        }
        findfac(p,k);
        findfac(n/p,k);
    }
    
    __int128 inv(__int128 a,__int128 p){
        return quick(a,p-2,p);
    }
    int main()
    {
        ll t,p,prime;
        __int128 ans;
        scanf("%lld",&t);
        while (t--)
        {
            scanf("%lld",&p);
            for (ll i=p-1; i>=2; i--)
            {
                if (Miller_Rabin(i))
                {
                    prime=i;
                    break;
                }
            }
            ans=p-1;
            for (__int128 i=p-1;i>prime;i--){
                ans=ans*inv(i,p)%p;
            }
            printf("%lld
    ",(ll)ans);
        }
    }
    

      

    #include <bits/stdc++.h>
     
    using namespace std;
     
    typedef long long ll;
     
    const ll N=200010;
     
    ll w[N],b[N],n,m;
     
    struct node{
        ll num,sum;
    }t[N*4];
     
    struct data{
        ll num,rk,id;
    }a[N];
     
    inline void build(ll rt,ll l,ll r) {
        t[rt].num = t[rt].sum = 0;
        if (l == r) {
            return;
        }
        ll mid = (l + r) >> 1;
        build(rt << 1, l, mid);
        build(rt << 1 | 1, mid + 1, r);
    }
     
    inline void change(ll rt,ll pos,ll l,ll r) {
        if (l == r) {
            t[rt].num = 1;
            t[rt].sum = b[pos];
            return;
        }
        ll mid = (l + r) >> 1;
        if (pos <= mid) {
            change(rt << 1, pos, l, mid);
        } else {
            change(rt << 1 | 1, pos, mid + 1, r);
        }
        t[rt].sum = t[rt << 1].sum + t[rt << 1 | 1].sum;
        t[rt].num = t[rt << 1].num + t[rt << 1 | 1].num;
    }
     
    inline ll query(ll rt,ll w,ll l,ll r) {
        if (l == r) {
            return t[rt].sum <= w ? t[rt].num : 0;
        }
        ll mid=(l+r)>>1;
        if (t[rt << 1].sum <= w) {
            return t[rt << 1].num + query(rt << 1 | 1, w - t[rt << 1].sum,mid+1,r);
        } else {
            return query(rt << 1, w, l, mid);
        }
    }
     
    inline bool cmp1(data a,data b) {
        return a.num < b.num;
    }
     
    inline bool cmp2(data a,data b) {
        return a.id < b.id;
    }
     
    int main() {
        int t;
        scanf("%d", &t);
        while (t--) {
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++) {
                scanf("%lld", &w[i]);
                a[i].id = i;
                a[i].num = w[i];
            }
            sort(a + 1, a + n + 1, cmp1);
            for (int i = 1; i <= n; i++) {
                a[i].rk = i;
                b[i] = a[i].num;
            }
            sort(a + 1, a + n + 1, cmp2);
            build(1, 1, n);
            for (int i = 1; i <= n; i++) {
                printf("%lld ", i - query(1, m - w[i], 1, n) - 1);
                change(1, a[i].rk, 1, n);
            }
            printf("
    ");
        }
    }
    

      

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef pair<int,int> PI;
    const int maxn=5000;
    const int inf=0x3f3f3f3f;
    int a[maxn];
    
    
    struct Min_Cost_Max_Flow{
        struct edge{
            int to,cap,cost,rev;
            edge(){};
            edge(int _to,int _cap,int _cost,int _rev):to(_to),cap(_cap),cost(_cost),rev(_rev){};
        };
        vector<edge>E[maxn];
        int h[maxn],n,d[maxn],preV[maxn],preE[maxn];
        void init(int n){
            this->n=n;
            for (int i=0;i<=n;i++){
                E[i].clear();
                h[i]=0;
            }
        }
        void add(int from,int to,int cap,int cost){
            E[from].push_back(edge(to,cap,cost,E[to].size()));
            E[to].push_back(edge(from,0,-cost,E[from].size()-1));
        }
    
        PI dijkstra(int s,int t,int f){
            int cost=0,flow=0;
            for (int i=0;i<=n;i++){
                h[i]=0;
            }
            while (f){
                priority_queue<PI,vector<PI>,greater<PI> >q;
                for (int i=0;i<=n;i++){
                    d[i]=inf;
                }
                d[s]=0;
                q.push(make_pair(0,s));
                while (!q.empty()){
                    PI now=q.top();
                    q.pop();
                    int v=now.second;
                    if (d[v]<now.first){
                        continue;
                    }
                    for (int i=0;i<E[v].size();i++){
                        edge &e=E[v][i];
                        if (e.cap>0&&d[e.to]>d[v]+e.cost+h[v]-h[e.to]){
                            d[e.to]=d[v]+e.cost+h[v]-h[e.to];
                            preV[e.to]=v;
                            preE[e.to]=i;
                            q.push(make_pair(d[e.to],e.to));
                        }
                    }
                }
                if (d[t]==inf)break;
                for (int i=0;i<=n;i++){
                    h[i]+=d[i];
                }
                int d=f;
                for (int i=t;i!=s;i=preV[i]){
                    d=min(d,E[preV[i]][preE[i]].cap);
                }
                f-=d;
                flow+=d;
                cost+=d*h[t];
                for (int i=t;i!=s;i=preV[i]){
                        edge &e=E[preV[i]][preE[i]];
                        e.cap-=d;
                        E[i][e.rev].cap+=d;
                }
            }
            return make_pair(flow,cost);
        }
    }G;
    
    int main() {
        int t,k,n;
        scanf("%d", &t);
        while (t--) {
            scanf("%d%d", &n, &k);
            for (int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
            }
            G.init(2*n+2);
            int S = 0, T = 2 * n + 2;
            G.add(S, n * 2 + 1, k, 0);
            for (int i = 1; i <= n; i++) {
                G.add(n * 2 + 1, i, 1, 0);
                G.add(i, n + i, 1, -a[i]);
                G.add(n + i, T, 1, 0);
            }
            for (int i = 1; i <= n; i++) {
                for (int j = i + 1; j <= n; j++) {
                    if (a[i] <= a[j]) {
                        G.add(n + i, j, 1, 0);
                    }
                }
            }
            PI ans=G.dijkstra(S,T,inf);
            printf("%d
    ",-ans.second);
        }
    }
    

      

    题意:要求把一个序列分成连续的k块(可以去掉后缀),使得权值和最大的那一块权值最小,求出这个最小值

    思路:先求前缀和leftSum[],然后对前缀和离散化;
    对leftSum[]排序并去重得到pre[];
    设f[i]=前i个数最多能分成的块数;
    二分答案,设答案为x;
    则转移方程为f[i]=max(f[j])+1,leftSum[i]-leftSum[j]<=x,j<i
    不能O(n^2)转移,想办法加速;
    以离散化后的pre[]的rank为下标,f为权值建立线段树;
    线段树需要实现单点修改、区间求最大值操作;
    每次求f[i]时,令L=lower_bound(pre+1,pre+1+num,leftSum[i]-x),其中num为pre[]离散化后数字个数,
    然后只需求得线段树[L,num]区间内的最大值_max,将f[i]更新为=_max+1即可,此时别忘了用新得到的f[i]去update线段树。
    代码中注意一些小细节要处理好。
    总时间复杂度为O(n*(logn)^2).

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    int tot;
    ll mx[maxn*4],b[maxn],dp[maxn],n,m,sum[maxn],a[maxn];
    void build(int rt,int l,int r) {
        if (l == r) {
            mx[rt] = -1;
            return;
        }
        int mid=(l+r)>>1;
        build(rt << 1, l, mid);
        build(rt << 1 | 1, mid + 1, r);
        mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
    }
    
    void update(int rt,int l,int r,int p,ll val) {
        if (l == r) {
            mx[rt] = max(mx[rt], val);
            return;
        }
        int mid = (l + r) >> 1;
        if (p <= mid) update(rt << 1, l, mid, p, val); else update(rt << 1 | 1, mid + 1, r, p, val);
        mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
    }
    int query(int rt,int l,int r,int L,int R) {
        if (L > R) return -1;
        if (L <= l && r <= R) {
            return mx[rt];
        }
        int mid = (l + r) >> 1, ans = -1;
        if (L <= mid) ans = max(ans, query(rt << 1, l, mid, L, R));
        if (R > mid) ans = max(ans, query(rt << 1 | 1, mid + 1, r, L, R));
        return ans;
    }
    
    bool solve(ll mid) {
        build(1, 1, tot);
        update(1, 1, tot, lower_bound(b + 1, b + 1 + tot, 0) - b, 0);
        for (int i = 1; i <= n; i++) {
            int p = lower_bound(b + 1, b + 1 + tot, sum[i] - mid) - b;
            int p1 = lower_bound(b + 1, b + 1 + tot, sum[i]) - b;
            int tmp = query(1, 1, tot, p, tot);
            if (tmp == -1) dp[i] = -1;
            else dp[i] = tmp + 1;
            update(1, 1, tot, p1, dp[i]);
            if (dp[i] >= m) return 0;
        }
        return 1;
    }
    
    int main() {
        int _;
        scanf("%d", &_);
        while (_--) {
            scanf("%lld%lld", &n, &m);
            for (int i = 1; i <= n; i++) {
                scanf("%lld", &a[i]);
                sum[i] = sum[i - 1] + a[i];
                b[i] = sum[i];
            }
            b[n + 1] = 0;
            sort(b + 1, b + 1 + n + 1);
            tot = unique(b + 1, b + n + 1 + 1) - (b + 1);
            ll l = -2e14, r = 2e14;
            while (l < r) {
                ll mid = (l + r) >> 1;
                if (solve(mid)) l = mid + 1; else r = mid;
            }
            printf("%lld
    ", l);
        }
    }
    
  • 相关阅读:
    css单位px,em,rem区别
    html视口单位:vw,vh,rem
    Codeforces Round #270 A. Design Tutorial: Learn from Math【数论/埃氏筛法】
    Codeforces Round #306 (Div. 2) A. Two Substrings【字符串/判断所给的字符串中是否包含不重叠的“BA” “AB”两个字符串】
    Codeforces Round #267 (Div. 2) B. Fedor and New Game【位运算/给你m+1个数让你判断所给数的二进制形式与第m+1个数不相同的位数是不是小于等于k,是的话就累计起来】
    Codeforces Round #369 (Div. 2) A. Bus to Udayland【字符串/二维字符数组求连起来的座位并改为其他字符】
    Codeforces Round #289 (Div. 2, ACM ICPC Rules) A. Maximum in Table【递推】
    Codeforces Round #191 (Div. 2) A. Flipping Game【*枚举/DP/每次操作可将区间[i,j](1=<i<=j<=n)内牌的状态翻转(即0变1,1变0),求一次翻转操作后,1的个数尽量多】
    Codeforces Round #377 (Div. 2) A. Buy a Shovel【暴力/口袋里面有无限枚 10 元和一枚 r 面值的硬币,问最少可以买多少把价值为 k 的铁铲】
    Good Bye 2016 A. New Year and Hurry【贪心/做题目每道题花费时间按步长为5等差增长,求剩余时间够做几道题】
  • 原文地址:https://www.cnblogs.com/Accpted/p/11265726.html
Copyright © 2020-2023  润新知