集训Day2

雅礼集训2017Day2

T1

给你一个水箱,水箱里有n-1个挡板,水遵循物理定律

给你m个条件,表示第i个格子上面y+1高度的地方有或没有水

现在给你无限的水从任意地方往下倒,问最多满足多少条件

n,m 1e5

SOL:

考虑答案的表示方法,肯定是类似于dp["区间1到n"]这种的

“区间1到n”这个东西我们可以状压,就过了20%

另外10%的数据只有“有水”的条件 我们cout<<m

另外30%的n平方做法肯定是要用到dp(我没有想出来这个东西怎么搞到n平方)

。。。

这里是全知全能的XiongGod提供的一种n平方做法

对于每一个条件,可以将其视为l到r区间的最高/最低高度为x;

把所有条件记录下来后就成了区间选择问题的版题,分成上下界两种讨论dp就好了

考虑暴力碾标算

一个区间能能不能“有水”取决于中间最长的那个木板

于是可以考虑递归建一棵“线段树”

这样一个区间的问题就可以递归到左右儿子解决

且因为这是棵线段树,最多nlogn个点

然后树形DP

$d[i]$表示i节点水没有漫出去的情况

$f[i]$表示i节点水漫出去的情况

式子由于...这是要给学妹(实际只有学弟吧?)看的

所以你们自己推吧

T2

一个100*100的棋盘,有地方有障碍

Alice和Bob两个人玩游戏,Alice放一个棋子,Bob先手二人轮流移动棋子

要求:不能移到障碍上且走过的地方不能走

不能动就输了

求Alice的必胜点

SOL:

原题啊...

将棋盘黑白染色建出二分图 有障碍直接跳过就行了

考虑对于一个完美匹配,Bob(先手)按匹配边走就可以了

对于不完美的最大匹配,Alice可以把棋放在“不一定是最大匹配”的地方,让Bob走非匹配边,自己走匹配边

现在就是要考虑如何求这个“不一定是最大匹配”的点

跑完dinic,从S开始跑未满流的边,跑到左边的且非S的点就是“不一定是最大匹配”的

T开始跑未满流的边,跑到右边且非T的点就是“不一定是最大匹配的”

为什么正确可以通过交错路定理来证明一下

时间复杂度是O(您用的二分图匹配算法 + 棋盘大小)

100 + 100 + 0 = 200?

T3前30随便写可是没时间写了...

话说是不是上午时间不够啊

如果再给我半个小时就是100 + 100 + 30 = 230了(再次大众分

#include<bits/stdc++.h>
#define LL long long
inline int read() {
    int x = 0,f = 1;
    char ch = getchar();
    for(; !isdigit(ch); ch = getchar())if(ch == '-')f = -f;
    for(; isdigit(ch); x = 10 * x + ch - '0',ch = getchar());
    return x * f;
}
const int maxn = 2e5 + 10,inf = 2147483233;
int n,m,N;
int fa[maxn],bot[maxn],top[maxn],dx[maxn];
int ST[20][maxn];
int son[maxn][2];
int f[maxn],d[maxn];

struct block {
    int h,pos;
} hs[maxn];
bool cmp(const block &a,const block &b) {
    if(a.h == b.h)return a.pos < b.pos;
    return a.h < b.h;
}
struct info {
    int h,type;
    bool operator < (const info &a)const {
        if(h == a.h)return type < a.type;
        return h < a.h;
    }
};

std::vector<info> vec[maxn];

inline int find(int x) {
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

int main() {
    int T = read();
    while(T--) {
        n = read(),m = read();
        N = n;
        memset(dx,0,sizeof(dx));
        memset(fa,0,sizeof(fa));
        memset(f,0,sizeof(f));
        memset(d,0,sizeof(d));
        int S,T,sum,sz,tmp;
        for(int i=1; i<n; i++) {
            hs[i].h = read();
            hs[i].pos = i;
        }
        std::sort(hs + 1,hs + n,cmp);
        bot[0] = inf;
        for(int i=1; i<=n; i++)top[i] = i,fa[i] = i;
        for(int i=1; i<n; i++) {
            int fx = find(hs[i].pos),fy = find(hs[i].pos + 1);
            bot[++N] = hs[i].h;
            ST[0][N] = 0;
            ST[0][top[fx]] = N;
            ST[0][top[fy]] = N;
            son[N][0] = top[fx],son[N][1] = top[fy];
            fa[fy] = fx;
            top[fx] = N;
        }
        for(int i=1; i<=N; i++)vec[i].clear();
        for(int i=1; i<=18; i++)
            for(int j=1; j<=N; j++)
                ST[i][j]=ST[i-1][ST[i-1][j]];
        int x,y,k;
        for(int i=1; i<=m; i++) {
            x = read(),y = read(),k = read();
            for(int j=18; j>=0; j--)
                if(bot[ST[j][x]] <= y)x = ST[j][x];
            vec[x].push_back((info) {y,k});
            dx[x] += !k;
        }
        for(int i=1; i<=N; i++)std::sort(vec[i].begin(),vec[i].end());
        for(int i=1; i<=N; i++) {
            if(!vec[i].empty()) {
                sz = vec[i].size();
                S = 0;
                d[i] = sum = dx[i] + ( i > n ? f[son[i][0]] + f[son[i][1]] : 0);
                while(S < sz) {
                    T = S;
                    tmp = (vec[i][T].type ? 1 : -1);
                    while(T + 1 < sz && vec[i][T+1].h == vec[i][T].h)
                        ++T,tmp += (vec[i][T].type ? 1 : -1);
                    sum += tmp;
                    d[i] = std::max(d[i],sum);
                    S = T + 1;
                }
                f[i] = sum;
            }
            if(i > n) {
                d[i] = std::max(d[i],dx[i] + d[son[i][0]] + d[son[i][1]]);
                f[i] = std::max(f[i],f[son[i][0]] + f[son[i][1]]);
            }
        }
        printf("%d\n",d[N]);
    }
}
T1(压行太严重就用了Astyle)
#include<bits/stdc++.h>
using namespace std;
const int _MAX = 110,MAX_POINT = 21010,MAXE = 1000010,inf = 2147483233;
const int dx[] = {0,1,-1,0,0};
const int dy[] = {0,0,0,1,-1};
int ans[MAX_POINT];
int m,n;
int S = 0,T = MAX_POINT - 1;
char s[_MAX][_MAX];
int pos[_MAX][_MAX],col[MAX_POINT],vis[MAX_POINT];
struct DINIC
{
    int first[MAX_POINT],cnt;
    int next[MAXE],to[MAXE],caps[MAXE];
    int deep[MAX_POINT];
    DINIC(){cnt = 1;}
    void add(int x,int y,int f) 
    {
        next[++cnt] = first[x];
        to[cnt] = y;
        caps[cnt] = f;
        first[x] = cnt;
    }
    void insert(int x,int y,int f) 
    {
        add(x,y,f);
        add(y,x,0);
    }
    bool BFS() 
    {
        queue<int> q;
        memset(deep,0,sizeof(deep));
        deep[S] = 1;
        q.push(S);
        while(!q.empty()) 
        {
            int x = q.front(); q.pop();
            for(int i = first[x]; i; i = next[i])
                if(caps[i] && !deep[to[i]])
                {
                    deep[to[i]] = deep[x] + 1;
                    q.push(to[i]);
                    if(to[i] == T)    return true;
                }
        }
        return false;
    }
    int dfs(int x,int f)
    {
        if(x == T)    return f;
        int temp = f;
        for(int i = first[x]; i; i = next[i])
            if(caps[i] && deep[to[i]] == deep[x] + 1 && temp)
            {
                int w = dfs(to[i],min(caps[i],temp));
                if(!w) deep[to[i]] = 0;
                caps[i] -= w;
                caps[i^1] += w;
                temp -= w;
            }
        return f - temp;
    }
}G;

int ctt;
void DFS(int x,int f)
{
    vis[x] = 1;
    if(col[x] == f && x != S && x != T)ans[++ctt] = x;
    for(int i = G.first[x]; i; i = G.next[i])
        if(G.caps[i] == f && !vis[G.to[i]])DFS(G.to[i],f);
}
void solveGraph()
{
    for(int i = 1; i <= m; i++)
        for(int j = 1; j <= n; j++) 
        {
            if(s[i][j] == '#')    continue;
            if(!((i + j)&1))G.insert(S,pos[i][j],1),col[pos[i][j]] = 1;
            else 
            {
                G.insert(pos[i][j],T,1);
                continue;
            }
            for(int k = 1; k <= 4; k++) 
            {
                int fx = i + dx[k],fy = j + dy[k];
                if(fx < 1 || fy < 1 || fx > m || fy > n)    continue;
                if(s[fx][fy] == '.')G.insert(pos[i][j],pos[fx][fy],1);
            }
        }
    while(G.BFS())G.dfs(S,inf);
    DFS(S,1);memset(vis,0,sizeof(vis));DFS(T,0);
}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i = 1; i <= m; i++)
        scanf("%s",s[i] + 1);
    int cnt = 0;
    for(int i = 1; i <= m; i++)
        for(int j = 1; j <= n; j++)
            pos[i][j] = ++cnt;
    solveGraph();
    printf("%d\n",ctt);
    sort(ans + 1,ans + ctt + 1);
    for(int i = 1; i <= ctt; i++)printf("%d %d\n",(ans[i] - 1) / n + 1,(ans[i] - 1) % n + 1);
    return 0;
}
T2

猜你喜欢

转载自www.cnblogs.com/Kong-Ruo/p/9158395.html