8.9 Round 1

今天是这几天考试中唯一一次发挥正常一点儿的...

T1:https://www.luogu.org/problem/T93119

这么小的数据,O(n^3)暴力就行

而我非常愚蠢加个二分,一样可以过

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<climits>
#include<map>
#include<queue>
#include<cmath>
using namespace std;
#define O(x) cout << #x << " " << x << endl;
#define B cout << "breakpoint" << endl;
#define clr(a) memset(a,0,sizeof(a));
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
const int maxn = 305;
int a1[maxn],a2[maxn];
int n,k;
char s[maxn];
inline bool check(int d)
{
    for(int i = 1;i + d - 1<= n;i++)
        for(int j = 1;j + d - 1 <= n;j++)
            {
                int cnt = 0;
                for(int t = 0;t < d;t++)
                    if(a1[i + t] != a2[j + t]) cnt++;
                if(cnt <= k) return 1;
            }
    return 0;
}
int main()
{
    freopen("master.in","r",stdin);
    freopen("master.out","w",stdout);
    n = read(),k = read();
    scanf("%s",s); for(int i = 1;i <= n;i++) a1[i] = (int)s[i - 1] - 'a' + 1;
    scanf("%s",s); for(int i = 1;i <= n;i++) a2[i] = (int)s[i - 1] - 'a' + 1;
    int l = 0,r = n;
    while(l < r)
    {
        int mid = (l + r + 1) >> 1;
        if(check(mid)) l = mid;
        else r = mid - 1;
    }
    printf("%d",l);
}
/*
7 2
aabbaba
bababbc
*/
View Code

T2:https://www.luogu.org/problem/T93120

考场上自信以为自己写的正解,没想到复杂度算错...

下次以为切题的时候,一定要好好算复杂度

70pts:f[u][s]:位于点u,还剩s条边可走

枚举起点s,容易处理环的情况

O(N^3)

正解:不考虑环,对于一条边u->v,它对答案的贡献是(d[u] - 1) *(d[v] - 1);

考虑去掉三元环,令s1为u能到达的点集,s2为v能到达的点集,这样对于s1与s2的并集,他们都可以成为三元环

于是统计并集中的点数,减去答案即可

用bitset记录点集,O(n^3 / 32)

bitset怎么用么...:https://www.cnblogs.com/zwfymqz/archive/2018/04/02/8696631.html

/*#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<climits>
#include<map>
#include<queue>
#include<cmath>
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
using namespace std;
#define O(x) cout << #x << " " << x << endl;
#define B cout << "breakpoint" << endl;
#define clr(a) memset(a,0,sizeof(a));
typedef long long ll;
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
const int maxn = 1505;
struct edge
{
    int to,next;
}e[maxn * maxn];
int fir[maxn],alloc;
void adde(int u,int v)
{
    e[++alloc].next = fir[u]; fir[u] = alloc; e[alloc].to = v;
    swap(u,v);
}
int s;
ll f[maxn][4];//f[u][step] : 在u,剩step条边可走的方案 
ll dfs(int u,int pre,int step)//在u,前一个点为pre,剩step条边可走 的方案数 
{
    if(f[u][step]) return f[u][step];
    if(step == 0) return 1ll;
    for(int i = fir[u];i;i = e[i].next)
    {
        int v = e[i].to;
        if(v == s) continue;
        f[u][step] += dfs(v,u,step - 1); 
    }
    if(step == 1) f[u][step]--;
    return f[u][step];
}
int main()
{
    freopen("tour.in","r",stdin);
    freopen("tour.out","w",stdout);
    int n = read();
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)
            {
                int x;
                scanf("%1d",&x);
                if(x) adde(i,j);
            }
    ll ans = 0;
    for(int i = 1;i <= n;i++)
    {
        clr(f); s = i;
        ans += dfs(s,0,3);
    }
    printf("%lld",ans);
}*/
/*
4
0101
1010
0101
1010
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<climits>
#include<map>
#include<queue>
#include<cmath>
#include<bitset>
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
using namespace std;
#define O(x) cout << #x << " " << x << endl;
#define B cout << "breakpoint" << endl;
#define clr(a) memset(a,0,sizeof(a));
typedef long long ll;
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
typedef long long ll;
const int maxn = 1505;
int d[maxn];
bitset<1505> in[maxn];
int main()
{
    freopen("tour.in","r",stdin);
    freopen("tour.out","w",stdout);
    int n = read();
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)
        {
            int x; scanf("%1d",&x);
            if(x) d[i]++,in[i][j] = 1;
        }
    ll ans = 0;
    for(int i = 1;i <= n;i++)
        for(int j = 1;j < i;j++)
        {
            if(!in[i][j]) continue;
            ll x = 1ll * (in[i] & in[j]).count();
            ans += (d[i] - 1) * (d[j] - 1) - x;
        }
    printf("%lld",ans << 1);
}
View Code

T3:https://www.luogu.org/problem/T93121

考场上Trie树乱搞,至今不知道为什么是错的...

正解是优化建边

对于每一个i,把val[i]拆出来,i->val[i]连一条边权为1的边,然后val[i]向val[i]去掉一个1的权点连边,边权为0

先bfs,对于队首u,先走u的边权为1的边,再dfs边权为0的边

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<climits>
#include<map>
#include<queue>
#include<cmath>
using namespace std;
#define O(x) cout << #x << " " << x << endl;
#define B cout << "breakpoint" << endl;
#define clr(a) memset(a,0,sizeof(a));
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
const int maxn = 2e6 + 5;
struct edge
{
    int to,next,cost;
}e[maxn << 1];
int fir1[maxn],alloc,fir2[maxn];
void adde(int u,int v,int op)
{
    if(op == 1) e[++alloc].next = fir1[u], fir1[u] = alloc, e[alloc].to = v;
    else e[++alloc].next = fir2[u],fir2[u] = alloc,e[alloc].to = v;
}
const int M = 1 << 20;
int dis[maxn];
queue<int> q;
int n,m;
void dfs(int u,int d)
{
    if(dis[u] >= 0) return;
    dis[u] = d;
    q.push(u);
    for(int i = fir2[u];i;i = e[i].next) dfs(e[i].to,d);
    if(u > M) return;
    for(int i = 0;i < 20;i++) if(u >> i & 1) dfs(u ^ (1 << i),d);
}
void bfs()
{
    memset(dis,-1,sizeof(dis));
    dis[M + 1] = 0;
    q.push(M + 1);
    dfs(M + 1,0);
    while(q.size())
    {
        int u = q.front(); q.pop();
        for(int i = fir1[u];i;i = e[i].next) dfs(e[i].to,dis[u] + 1); 
    }
    for(int i = 1;i <= n;i++)
        printf("%d
",dis[M + i]);
}
int main()
{
    freopen("walk.in","r",stdin);
    freopen("walk.out","w",stdout);
    n = read(),m = read();
    for(int i = 1;i <= n;i++) 
    {
        int x = read();
        adde(M + i,x,1);
        adde(x,M + i,2);
    }
    for(int i = 1;i <= m;i++)
    {
        int u = read(),v = read();
        adde(u + M,v + M,1);
    }
    bfs();
}
View Code
原文地址:https://www.cnblogs.com/LM-LBG/p/11329507.html