8.10 Round 1

要提高代码能力

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

送分背包

#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;
}
typedef long long ll;
const int N = 55;
const int mod = 1e9 + 7;
ll f[N][N][2050];
int main()
{
    freopen("number.in","r",stdin);
    freopen("number.out","w",stdout); 
    int n = read(),K = read(),s = read();
    f[0][0][0] = 1ll;
    for(int i = 1;i <= n;i++)
        for(int j = 0;j <= K;j++)
            for(int k = 0;k <= s;k++)
            {
                (f[i][j][k] += f[i - 1][j][k]) %= mod;
                if(k >= i && j >= 1) (f[i][j][k] += f[i - 1][j - 1][k - i]) %= mod;
            }
    printf("%lld",f[n][K][s]);
}
View Code

 

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

一个圆恰好被若干圆分割时,对答案贡献2

其余贡献1

将圆按半径排序,线段树维护哪些点被覆盖过

#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;
}
typedef long long ll;
const int maxn = 6e5 + 5;
struct node1
{
    int l,r,ctr,d;
    bool operator < (const node1& b) const
    {
        return d < b.d;
    }
}a[maxn];
int b[maxn];
int tot;
bool vis[maxn];
struct seg_tr
{
    int sum[maxn << 2],lazy[maxn << 2];
    #define ls i << 1
    #define rs i << 1 | 1
    inline void up(int i) { sum[i] = sum[ls] + sum[rs]; }
    inline void down(int i,int l,int r) { int mid = l + r >> 1; if(lazy[i]) lazy[ls] = lazy[rs] = 1,sum[ls] = mid - l + 1,sum[rs] = r - mid,lazy[i] = 0; }
    void change(int i,int l,int r,int ql,int qr)
    {
        if(l == ql && r == qr)
        {
            sum[i] = r - l + 1;
            lazy[i] = 1;
            return;
        }
        down(i,l,r);
        int mid = l + r >> 1;
        if(qr <= mid) change(ls,l,mid,ql,qr);
        else if(ql > mid) change(rs,mid + 1,r,ql,qr);
        else change(ls,l,mid,ql,mid),change(rs,mid + 1,r,mid + 1,qr);
        up(i);
    }
    int query(int i,int l,int r,int ql,int qr)
    {
        if(l == ql && r == qr) return sum[i];
        down(i,l,r);
        int mid = l + r >> 1;
        if(qr <= mid) return query(ls,l,mid,ql,qr);
        else if(ql > mid) return query(rs,mid + 1,r,ql,qr);
        else return query(ls,l,mid,ql,mid) + query(rs,mid + 1,r,mid + 1,qr);
    }
}T;
int main()
{
    freopen("circle.in","r",stdin);
    freopen("circle.out","w",stdout); 
    int n = read();
    for(int i = 1;i <= n;i++)
    {
        a[i].ctr = read();
        int x = read();
        a[i].l = a[i].ctr - x; a[i].r = a[i].ctr + x;
        b[++tot] = a[i].l; b[++tot] = a[i].r;
        a[i].d = x;
    }
    sort(b + 1,b + 1 + tot);
    int l = unique(b + 1,b + 1 + tot) - b - 1;
    tot = l;
    for(int i = 1;i <= n;i++)
    {
        a[i].l = lower_bound(b + 1,b + 1 + tot,a[i].l) - b;
        a[i].r = lower_bound(b + 1,b + 1 + tot,a[i].r) - b;
    }
    sort(a + 1,a + 1 + n);
    int ans = 1;
    for(int i = 1;i <= n;i++)
    {
        if(T.query(1,1,n,a[i].l,a[i].r - 1) == a[i].r - a[i].l) ans += 2;
        else ans += 1;
        T.change(1,1,n,a[i].l,a[i].r - 1);
    }
    printf("%d",ans);
}
/*
4 
7 5 
-9 11 
11 9 
0 20
*/
View Code

 

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

考场想的正解,没写出来

要提高代码能力

先缩点,枚举哪一条边反向,可以看出,需要维护1->i的最长路径,i->1的最长路径

所以spfa跑最长路;考场上我想拆点,代码会复杂;其实对于点的最短路也可以一样跑,不需要拆开

#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;
}
typedef long long ll;
const int maxn = 2e5 + 5;
struct node
{
    int u,v;
}a[maxn];
struct edge
{
    int to,next;
}e[maxn],rev[maxn];
int head[maxn],cnt;
void adde2(int u,int v) { rev[++cnt].next = head[u],head[u] = cnt,rev[cnt].to = v; }
int fir[maxn],alloc;
void adde1(int u,int v) { e[++alloc].next = fir[u],fir[u] = alloc,e[alloc].to = v; }
int dfn[maxn],idx,col[maxn],b[maxn],tot,low[maxn],st[maxn],top,n,m;
bool instack[maxn];
void tarjan(int u)
{
    low[u] = dfn[u] = ++idx;
    instack[u] = 1;
    st[++top] = u;
    for(int i = fir[u];i;i = e[i].next)
    {
        int v = e[i].to;
        if(!dfn[v]) 
        {
            tarjan(v); 
            low[u] = min(low[u],low[v]);
        }
        else if(instack[v]) low[u] = min(low[u],dfn[v]);
    }
    if(low[u] == dfn[u])
    {
        tot++;
        while(st[top] != u)
        {
            int k = st[top];
            col[k] = tot;
            instack[k] = 0;
            b[tot]++;
            top--;
        }
        col[u] = tot;
        instack[u] = 0,b[tot]++;
        top--;
    }
}
int d1[maxn],s;
bool vis[maxn];
void spfa1()
{
    clr(vis);
    queue<int> q;
    q.push(s); d1[s] = b[s];
    while(q.size())
    {
        int u = q.front(); q.pop();
        //O(u);
        //printf("%d %d\n",d1[u],u);
        vis[u] = 0;
        for(int i = fir[u];i;i = e[i].next)
        {
            int v = e[i].to;
            if(d1[v] < d1[u] + b[v])
            {
                d1[v] = d1[u] + b[v];
                if(!vis[v]) vis[v] = 1,q.push(v);
            }
        }
    }
}//d1:1->其他,d2:其他->1 
int d2[maxn];
void spfa2()
{
    clr(vis);
    queue<int> q;
    q.push(s); d2[s] = b[s];
    while(q.size())
    {
        int u = q.front(); q.pop();
        //printf("%d %d\n",d2[u],u);
        vis[u] = 0;
        for(int i = head[u];i;i = rev[i].next)
        {
            int v = rev[i].to;
            if(d2[v] < d2[u] + b[v])
            {
                d2[v] = d2[u] + b[v];
                if(!vis[v]) vis[v] = 1,q.push(v);
            }
        }
    }
}
int main()
{
    freopen("wander.in","r",stdin);
    freopen("wander.out","w",stdout); 
    n = read(),m = read();
    for(int i = 1;i <= m;i++)
    {
        int u = read(),v = read();
        a[i].u = u,a[i].v = v;
        adde1(u,v);
    }
    for(int i = 1;i <= n;i++) if(!dfn[i]) tarjan(i);
    clr(fir); alloc = 0; clr(head); cnt = 0;
    //for(int i = 1;i <= n;i++) printf("%d ",col[i]);
    //printf("\n");
    for(int i = 1;i <= m;i++)
    {
        int u = col[a[i].u],v = col[a[i].v];
        if(u == v) continue;
        //printf("%d %d\n",u,v);
        adde1(u,v);
        adde2(v,u);
    }
    s = col[1];
    //O(s);
    spfa1(); spfa2();
    int ans = b[s];
    for(int i = 1;i <= m;i++)
    {
        int u = col[a[i].u],v = col[a[i].v];
        if(u == v) continue;    
        //printf("%d %d\n",u,v);
        if(!d1[v] || !d2[u]) continue;
        ans = max(ans,d1[v] + d2[u] - b[s]);
    }
    printf("%d",ans); 

}
/*
7 10
1 2 
3 1 
2 5 
2 4 
3 7 
3 5 
3 6 
6 5 
7 2 
4 7
*/
    
View Code

 

posted on 2019-08-10 15:38  L_M_A  阅读(134)  评论(0编辑  收藏  举报

导航