• Summer training round2 #10(Training 30)


    A:签到题

    B!:搜索+DP

    #include<bits/stdc++.h>
    #define mp make_pair
    #define pi pair<int,int>
    using namespace std;
    const int dx[4]={-1,1,0,0};
    const int dy[4]={0,0,-1,1};
    int f[60][60][60],v[60][60],a[60][60],bx,by,ex,ey,n,m,l;
    pi q[2000010];
    char s[60];
    
    void bfs(int k)
    {
        int h=1,r=0;
        for (int i=1; i<=n; i++)
            for (int j=1; j<=m; j++)
                if (a[i][j])
                {
                    q[++r]=mp(i,j);
                    v[i][j]=1;
                }
    
        while (h<=r)
        {
            int i=q[h].first,j=q[h].second;
            v[i][j]=0; h++;
            for (int w=0; w<4; w++)
            {
                int x=i+dx[w],y=j+dy[w];
                if (!a[x][y]) continue;
                if (f[x][y][k]>f[i][j][k]+1)
                {
                    f[x][y][k]=f[i][j][k]+1;
                    if (!v[x][y])
                    {
                        q[++r]=mp(x,y);
                        v[x][y]=1;
                    }
                }
            }
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1; i<=n; i++)
        {
            scanf("%s",s+1);
            for (int j=1; j<=m; j++)
            {
                if (s[j]!='#') a[i][j]=1;
                if (s[j]=='R')
                {
                    bx=i;
                    by=j;
                }
                if (s[j]=='E')
                {
                    ex=i;
                    ey=j;
                }
            }
        }
        scanf("%s",s+1);
        l=strlen(s+1);
        for (int i=1; i<=n; i++)
            for (int j=1; j<=m; j++)
                for (int k=0; k<=l+1; k++) f[i][j][k]=1e9;
        int ans=1e9;
        f[bx][by][0]=0;
        for (int k=1; k<=l+1; k++)
        {
            bfs(k-1);
            ans=min(ans,f[ex][ey][k-1]);
            if (k==l+1) break;
            for (int i=1; i<=n; i++)
                for (int j=1; j<=m; j++)
                    if (a[i][j])
                    {
                        int pw;
                        if (s[k]=='L') pw=2;
                        if (s[k]=='R') pw=3;
                        if (s[k]=='U') pw=0;
                        if (s[k]=='D') pw=1;
                        int x=i+dx[pw],y=j+dy[pw];
                        if (a[x][y]) f[x][y][k]=min(f[i][j][k-1],f[x][y][k]);
                        else f[i][j][k]=min(f[i][j][k-1],f[i][j][k]);
                        f[i][j][k]=min(f[i][j][k-1]+1,f[i][j][k]);
                    }
        }
        printf("%d
    ",ans);
    }
    View Code

    C:贪心 每次放尽量右边

    #include <bits/stdc++.h>
    #define EPS 1.0e-9
    #define PI acos(-1.0)
    #define INF 30000000
    #define MOD 1000000007
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define pai pair<int,int>
    //using ll = long long;
    //using ull= unsigned long long;
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 100005;
    ll mod = 1e9 + 7;
    int a[maxn];
    int num[maxn];
    int main()
    {
            // freopen("oddfactor.in", "r", stdin);
            // freopen("out.txt", "w", stdout);
            int n,k,r;
            int leftt;
            int rightt;
            leftt=rightt=1;
            int anser=0;
            int sum=0;
            mem(num,0);
            cin >> n >> k >> r;
            for(int i=1;i<=k;i++)
            {
            scanf("%d",&a[i]);
            num[a[i]]++;
            }
            for(int i=1;i<=n;i++)
            {
            if(num[i])
            {
            if(sum)
            leftt=rightt,rightt=i+1;
            else
            rightt=i,sum++;
            }
            if(sum==0&&i-leftt==r-2)
            {
            rightt=i+1;
            anser++;
            sum++;
            }
            if(sum==1&&i-leftt==r-1)
            {
            leftt=rightt;
            rightt=i+1;
            anser++;
            }
            }
            cout<<anser<<endl;
            return 0;
    }
    View Code

    D!:首先假设做题顺序是i1,i2...in,那么最后罚时是n*t(i1)+(n-1)*t(i2)+...t(in)

    考虑罚时的期望,根据期望的线性性质,如果第i道题期望在Pi时解决,那么它对期望的贡献就是(n-Pi)*ti

    现在求所有可能罚时的总和,也就是我们只要求出每个题目的位置总贡献((n-Pi)*n!)即可

    观察阅读规则,对于每道题什么时候读,我们只要考虑比这道题容易或难的题的数目

    所以对第x道题,我们令f[i][j][p][r] 表示有i道比x简单的题还未读,j道比x难的题,p表示x有没有读,r表示当前读过r道比x简单的题,在这种情况下的位置总贡献

    (耗时相同的我们随便假定一个难以顺序,因为我们只在乎最后总的贡献)

     根据阅读规则很容易写出转移方程,具体见程序

    又观察可得,在每个固定状态下,不论是针对哪道题,f[]是不变的即通用的,因此总的复杂度为O(n^3)

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int mo=1e9+7;
    int f[320][320][2][320];
    ll d[320];
    int a[320],n,k;
    
    void inc(int &a,int b)
    {
        a+=b;
        if (a>mo) a-=mo;
    }
    
    int dp(int i,int j,int p,int r)
    {
        if (f[i][j][p][r]!=-1) return f[i][j][p][r];
        int s=-1,rr=r;
        if (i+j+p==0) s=k-r; //所有题都读过了
        else if (i+j+p<=n-k) //读过的题超过了k道
        {
            if (r) rr--; //先做最简单的
            else if (p==0) s=(i+j+k)*d[i+j]%mo;  //做当前考虑的这道并计算总的贡献
        }
        if (s==-1)
        {
            s=0; //三种可能的读题情况
            if (i) s=1ll*i*dp(i-1,j,p,rr+1)%mo; 
            if (j) inc(s,1ll*j*dp(i,j-1,p,rr)%mo);
            if (p) inc(s,dp(i,j,p-1,rr)%mo);
        }
        f[i][j][p][r]=s;
        return s;
    }
    
    int main()
    {
        memset(f,255,sizeof(f));
        d[0]=1;
        scanf("%d%d",&n,&k);
        for (int i=1; i<=n; i++)
            d[i]=d[i-1]*i%mo;
        for (int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        int ans=0;
        for (int i=1; i<=n; i++)
            ans=(ans+1ll*a[i]*dp(i-1,n-i,1,0)%mo)%mo;
        printf("%d
    ",ans);
    }
    View Code

    E!:

    好题,首先求出原先控制区域的凸包

    如果把问题一般化处理,就是求凸包插入一个点怎么变

    对于每一颗新增点i,凸包面积如果发生变化,一定是从凸包上两点l,r连向i

    i-r,i-l两条射线刚好能卡住原凸包,且原先凸包上l~r之间的点不再是边界

    根据凸包面积计算公式,如果我们找到l,r,那么很容易用前缀和求出答案

    为了寻找l,r,我们假定p1为凸包最左下的点,pm为凸包最右上的点

    考虑i的位置,分4种情况

    1. i在p1的左侧 2. i在pm的右侧

    3. i在p1,pm之间且在p1,pm连线的上方

    4. i在p1,pm之间且在p1,pm连线的下方

    情况1和情况2类似且较为简单,l,r一定分别在凸包的上凸壳和下凸壳上(也可能正好是p1,pm)

    根据i-r,i-l两条射线刚好能卡住原凸包的性质可以用二分快速找到

    情况3和情况4显然,l,r会同时落在上凸壳或下凸壳上,我们需要找到一个凸包的分界点k

    使得x[k-1]<x[i]<=x[k],这显然是可以用二分求出的,再在上(下)凸壳的左右区间分别用二分找到l,r即可

    示意图如下:

    其实,还有一个更简单的方法

    可以证明,如果要是新的凸包面积最大,那么增加的点应在整个点集的凸包上

    随着点在凸包上的逆时针(或顺时针移动),其对应的l,r也在凸包上做同向移动,由此就是two pointer的问题了

    但是写起来似乎很有细节问题,改日把这个方法补上

    另外注意这题答案会很大,double精度不够,又答案只有一位小数,直接判断着输出即可

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    struct po
    {
        int x,y;
        friend bool operator <(po a,po b)
        {
            if (a.x==b.x) return a.y<b.y;
            return a.x<b.x;
        }
        friend po operator -(po a,po b)
        {
            return (po){a.x-b.x,a.y-b.y};
        }
        friend po operator +(po a,po b)
        {
            return (po){a.x+b.x,a.y+b.y};
        }
        friend ll operator *(po a, po b)
        {
            return 1ll*a.x*b.y-1ll*a.y*b.x;
        }
    } p[100010],q[100010];
    int n,k,t;
    ll s[100010];
    
    int get(int l,int r,int i,int w)
    {
        while (l<r)
        {
            int m=(l+r)>>1;
            if ((q[m]-p[i])*(q[m+1]-p[i])*w>0) r=m;
            else l=m+1;
        }
        return l;
    }
    
    int bord(int l,int r,int i,int w)
    {
        while (l<r)
        {
            int m=(l+r)>>1;
            if ((q[m].x-p[i].x)*w<0) l=m+1;
            else r=m;
        }
        return l;
    }
    
    int main()
    {
        scanf("%d%d",&n,&k);
        for (int i=1; i<=n; i++)
            scanf("%d%d",&p[i].x,&p[i].y);
        sort(p+1,p+1+k);
        q[1]=p[1]; t=1;
        for (int i=2; i<=k; i++)
        {
            while (t>1&&(p[i]-q[t-1])*(q[t]-q[t-1])>=0) t--;
            q[++t]=p[i];
        }
        int m=t;
        for (int i=k-1;i;i--)
        {
            while (t>m&&(p[i]-q[t-1])*(q[t]-q[t-1])>=0) t--;
            q[++t]=p[i];
        }
        for (int i=1; i<t; i++)
            s[i+1]+=s[i]+q[i]*q[i+1];
        ll ans=s[t],tmp;
        for (int i=k+1; i<=n; i++)
        {
            if (p[i].x<q[1].x)
            {
                int l=get(1,m,i,1), r=get(m,t,i,-1);
                tmp=s[r]-s[l]+q[r]*p[i]+p[i]*q[l];
            }
            else if (p[i].x>q[m].x)
            {
                int l=get(1,m,i,-1),r=get(m,t,i,1);
                tmp=s[t]-s[r]+s[l]+q[l]*p[i]+p[i]*q[r];
            }
            else if ((q[m]-q[1])*(p[i]-q[1])>0)
            {
                int mid=bord(m,t,i,-1);
                if (mid>m&&(q[mid]-q[mid-1])*(p[i]-q[mid-1])>0) continue;
                int l=mid>m?get(m,mid-1,i,-1):m;
                int r=get(mid,t,i,1);
                tmp=s[t]-s[r]+s[l]+q[l]*p[i]+p[i]*q[r];
            }
            else {
                int mid=bord(1,m,i,1);
                if (mid>1&&(q[mid]-q[mid-1])*(p[i]-q[mid-1])>0) continue;
                int l=(mid>1)?get(1,mid-1,i,-1):1;
                int r=get(mid,m,i,1);
                tmp=s[t]-s[r]+s[l]+q[l]*p[i]+p[i]*q[r];
            }
            ans=max(ans,tmp);
        }
        printf("%lld",ans/2);
        if (ans&1) puts(".5"); else puts(".0");
    }
    
    方法一
    View Code

    F:2-sat问题

    #include <bits/stdc++.h>
    #define MAXN 10005
    using namespace std;
    struct TwoSat{
        int dfn[MAXN * 2], low[MAXN * 2], dfs_ind = 1, sccno[MAXN * 2], scc_cnt = 0, w[MAXN * 2];
        vector<int> G[MAXN * 2];
        stack<int> st;
        void Add(int u, int v) {
            G[u].push_back(v);
        }
        void Tarjan(int u)
        {
            dfn[u]=low[u]=dfs_ind++;
            st.push(u);
            for(int i=0; i < G[u].size(); i++)
            {
                int v = G[u][i];
                if(!dfn[v])
                {
                    Tarjan(v);
                    low[u]=min(low[u],low[v]);
                }else if(!sccno[v])
                {
                    low[u]=min(low[u],dfn[v]);
                }
            }
            if(dfn[u]==low[u])
            {
                scc_cnt++;
                while(true)
                {
                    int x=st.top();st.pop();
                    sccno[x]=scc_cnt;
                    w[scc_cnt]++;
                    if(x==u)break;
                }
            }
        }
        bool Solve(int m) {
            for(int i = 1; i <= m * 2; i++) {
                if(!dfn[i]) {
                    while(!st.empty())st.pop();
                    Tarjan(i);
                }
            }
            for(int i = 1; i <= m; i++){
                if(sccno[i] == sccno[i + m]) {
                    return false;
                }
            }
            return true;
        }
    }twosat;
    int n, r, l, x[MAXN], y[MAXN];
    int main() {
        scanf("%d%d%d", &n, &r, &l);
        for(int i = 1; i <= l; i++) {
            scanf("%d%d", &x[i], &y[i]);
        }
        for(int i = 1; i <= l; i++) {
            for(int j = 1; j <= l; j++) {
                if(i == j) continue;
                if(x[i] == x[j] && abs(y[i] - y[j]) <= 2 * r) {
                    twosat.Add(i + l, j);
                    twosat.Add(j + l, i);
                }
                if(y[i] == y[j] && abs(x[i] - x[j]) <= 2 * r) {
                    twosat.Add(i, j + l);
                    twosat.Add(j, i + l);
                }
            }
        }
        if(twosat.Solve(l)) {
            printf("YES
    ");
        }else {
            printf("NO
    ");
        }
        return 0;
    }
    View Code

    G!:首先把确定的拎出来,不确定的地方要使海岛尽可能多,那必定是将一格作为一个海岛

    不难想到将图黑白染色做而二分图的最大独立集

    #include<bits/stdc++.h>
    
    using namespace std;
    const int dx[4]={-1,1,0,0};
    const int dy[4]={0,0,-1,1};
    char s[100];
    int f[1610],b[60][60],a[60][60],v[60][60],cy[1610],cx[1610],n,m,ans,t;
    vector<int> g[1610];
    void dfs(int i,int j)
    {
        v[i][j]=1;
        for (int k=0; k<4; k++)
        {
            int x=i+dx[k],y=j+dy[k];
            if (x==0||x>n||y>m||y==0) continue;
            if (v[x][y]) continue;
            if (a[x][y]==-1) a[x][y]=0;
            if (a[x][y]==1) dfs(x,y);
        }
    }
    
    int work(int x)
    {
        for (int i=0; i<g[x].size(); i++)
        {
            int y=g[x][i];
            if (!f[y])
            {
                f[y]=1;
                if (!cy[y]||work(cy[y]))
                {
                    cx[x]=y;
                    cy[y]=x;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
        scanf("%d%d",&n,&m);
        for (int i=1; i<=n; i++)
        {
            scanf("%s",s+1);
            for (int j=1; j<=m; j++)
            {
                if (s[j]=='W') a[i][j]=0;
                if (s[j]=='C') a[i][j]=-1;
                if (s[j]=='L') a[i][j]=1;
            }
        }
        for (int i=1; i<=n; i++)
            for (int j=1; j<=m; j++)
                if (!v[i][j]&&a[i][j]==1)
                {
                    ans++;
                    dfs(i,j);
                }
    
        for (int i=1; i<=n; i++)
            for (int j=1; j<=m; j++)
                if (a[i][j]==-1) b[i][j]=++t;
        for (int i=1; i<=n; i++)
            for (int j=1; j<=m; j++)
                if ((i+j)%2==0)
                {
                    for (int k=0; k<4; k++)
                    {
                        int x=i+dx[k],y=j+dy[k];
                        if (b[x][y]) g[b[i][j]].push_back(b[x][y]);
                    }
                }
        int s=0;
        for (int i=1; i<=t; i++)
            if (g[i].size())
            {
                if (!cx[i])
                {
                    memset(f,0,sizeof(f));
                    s+=work(i);
                }
            }
        printf("%d
    ",ans+t-s);
    }
    View Code

    H:离散化后DP ans[i]表示取i个最少要漏掉多少个 不取的话就直接duan[i].r-duan[i-1].r取的话就duan[i].l-duan[cur].r-1

    #include <bits/stdc++.h>
    #define EPS 1.0e-9
    #define PI acos(-1.0)
    #define INF 30000000
    #define MOD 1000000007
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define pai pair<int,int>
    //using ll = long long;
    //using ull= unsigned long long;
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 200005;
    ll mod = 1e9 + 7;
    struct node
    {
     ll l;
     ll r;
    }duan[maxn];
    ll righ[maxn];
    ll ans[maxn];
    ll getit[maxn];
    bool cmp(node a,node b)
    {
     return b.r>a.r;
    }
    int main()
    {
            // freopen("oddfactor.in", "r", stdin);
            // freopen("out.txt", "w", stdout);
            ll n,m;
            ll anser;
            ll cur;
            cin >> n >> m;
            for(int i=1;i<=m;i++)
            scanf("%lld %lld",&duan[i].l,&duan[i].r);
            sort(duan+1,duan+1+m,cmp);
            ll now=0;
            for(int i=1;i<=m;i++)
            righ[i]=duan[i].r;
            for(int i=1;i<=m;i++)
            {
            cur=lower_bound(righ+1,righ+1+m,duan[i].l)-righ-1;
            ans[i]=min(ans[cur]+duan[i].l-duan[cur].r-1,ans[i-1]+duan[i].r-duan[i-1].r);
            }
            cout<<n+ans[m]-duan[m].r;
            return 0;
    }
    View Code

     I:贪心 每次肯定送尽可能最远的最优

    #include<math.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<sstream> //istringstream stm(string); stm >> x;
    #include<vector>
    #define INF 2139062143
    #define inf -2139062144
    #define ll long long
    using namespace std;
    struct point {
        ll pos,letter;
    };
    bool cmp(point p1, point p2) {
        return p1.pos < p2.pos;
    }
    vector<point> pzheng,pfu;
    int main() {
        ll n,k,i,j;
        scanf("%lld%lld",&n,&k);
        for(i=0; i<n; i++) {
            ll pos,x;
            scanf("%lld%lld",&pos,&x);
            if(pos >= 0) {
                pzheng.push_back({pos,x});
            } else {
                pfu.push_back({-pos,x});
            }
        }
        sort(pzheng.begin(),pzheng.end(),cmp);
        sort(pfu.begin(),pfu.end(),cmp);
    //    for(i=0;i<pzheng.size();i++){
    //        printf("%lld %lld
    ",pzheng[i].pos,pzheng[i].letter);
    //    }
        bool over = false;
        ll size = pzheng.size();
        ll cur = size - 1;
        ll ans = 0;
        if(size > 0) {
            while(!over) {
                if(pzheng[cur].letter > k) {
                    ll time = pzheng[cur].letter / k;
                    ans += time * pzheng[cur].pos * 2;
                    pzheng[cur].letter -= time * k;
                    if(pzheng[cur].letter == 0)    cur--;
                } else {
                    ll send = k;
                    ans += 2 * pzheng[cur].pos;
                    while(send > 0 && cur >= 0) {
                        ll last = pzheng[cur].letter;
                        pzheng[cur].letter = max((ll)0,pzheng[cur].letter - send);
                        send -= (last - pzheng[cur].letter);
                        if(send > 0 || pzheng[cur].letter == 0) {
                            cur--;
                        }
                    }
                }
                if(pzheng[0].letter == 0 || cur < 0) {
                    over = true;
                }
            }
        }
    
    
    
        over = false;
        size = pfu.size();
        if(size > 0) {
            cur = size - 1;
            while(!over) {
                if(pfu[cur].letter > k) {
                    ll time = pfu[cur].letter / k;
                    ans += time * pfu[cur].pos * 2;
                    pfu[cur].letter -= time * k;
                    if(pfu[cur].letter == 0)    cur--;
                } else {
                    ll send = k;
                    ans += 2 * pfu[cur].pos;
                    while(send > 0 && cur >= 0) {
                        ll last = pfu[cur].letter;
                        pfu[cur].letter = max((ll)0,pfu[cur].letter - send);
                        send -= (last - pfu[cur].letter);
                        if(send > 0 || pfu[cur].letter == 0) {
                            cur--;
                        }
                    }
                }
                if(pfu[0].letter == 0 || cur < 0) {
                    over = true;
                }
            }
        }
    
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    J:2016年网络赛题

    #include <bits/stdc++.h>
    #define EPS 1.0e-9
    #define PI acos(-1.0)
    #define INF 30000000
    #define MOD 1000000007
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define pai pair<int,int>
    //using ll = long long;
    //using ull= unsigned long long;
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 200005;
    int n,m;
    ll aaa[maxn][20];
    ll a[maxn];
    void init()
    {
     for(int i=1;(1<<i)<=n;i++)
            for(int j=1;j<=n-(1<<i)+1;j++)
     {
            aaa[j][i]=min(aaa[j][i-1],aaa[j+(1<<(i-1))][i-1]);
     }
    }
    ll runit(int l,int r)
    {
     int now;
     for(now=0;(1<<now)<=r-l+1;now++);
     now--;
     ll ans=min(aaa[l][now],aaa[r-(1<<now)+1][now]);
     return ans;
    }
    int cal(ll value,int x,int y)
    {
     if(x>y)
     return 0;
     if(value>a[x])
     return x;
     if(x==y)
     return 0;
     if(value<runit(x,y))
     return 0;
     int l=x,r=y,mid;
     while(r-l>1)
     {
            mid=(l+r)/2;
            if(value>=runit(x,mid))
            r=mid;
            else
            l=mid;
     }
     return r;
    }
    ll work(ll pop,int pop1,int pop2)
    {
     int flag=1;
     while(flag)
     {
            pop%=a[pop1];
            int now=cal(pop,pop1+1,pop2);
            if(!now)
            return pop;
            else
            pop1=now;
     }
    }
    int main()
    {
        cin >> n >> m;
        for(int i=1;i<=n;i++)
        {
            scanf("%I64d",&a[i]);
            aaa[i][0]=a[i];
        }
        init();
        while(m--)
        {
            ll cur,l,r;
            scanf("%I64d %I64d %I64d",&cur,&l,&r);
            //cin >> cur >> l >> r
            //cout<<cur<<" "<<l<<" "<<r<<endl;
            printf("%I64d
    ",work(cur,l,r));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    MYSQL--事务处理
    phpStudy + JspStudy 2014.10.02 下载
    ThinkPHP实现跨模块调用操作方法概述
    ThinkPHP整合百度Ueditor图文教程
    PHP获取今天、昨天、明天的日期
    获取客户端IP地址定位城市信息
    samba服务器概述
    Linux下好玩的命令
    一张网页的旅行
    PHP获取中英文混合字符串长度及截取
  • 原文地址:https://www.cnblogs.com/Aragaki/p/7368259.html
Copyright © 2020-2023  润新知