1101

240pts 题目比较简单 有AK机会但是我放弃了....
没开longlong 见祖宗.....

A 草地排水
时间限制 : - MS 空间限制 : - KB
评测说明 : 1s,256m
问题描述
【问题描述】 我们都知道,草地排水是一道简单的\(usaco\)网络流裸题。当然,网络流这么简单的知识点做这道题的各位大爷一定都很会做了。所以这道题和网络流并没有关系。
一场大雨过后,长春很多地势低洼的地方都被积水淹没了,\(everlasting\)家门口的草坪也不例外。脑小的\(everlasting\)当然不喜欢水啦,它找到了你去帮他家门口的草坪排水。
\(everlasting\)家门口的草坪可以近似的看作是一条一维直线。这条直线已经完全被积水淹没,你可以认为对于直线上的任意点,积水的深度都是无穷大的。\(everlasting\)\(n\)个自动排水装置,对于每个自动排水装置,都有一个作用范围你可以选择任意多个装置使用,以期望得到最大的作用效果总和。但需要注意的是,任意两个装置的作用范围都不能有丝毫的重叠(即使区间端点重叠也是不被允许的)。若你的方案中存在重叠的作用范围,那萌萌的$everlasting \(的家就会\)BOOM$的一声炸到天上去!你一定不希望这么糟糕的事情发生吧!

解:
简单\(DP\)
离散化后定义 \(f[j]\) 代表以j结尾的最大的值
按照右端点从左到右排序 保证每次讨论的时候前面已经被算过了
这道题不能有选或不选的决策 也就是说j位置一定选了
\(f[j]=max(f[k])+v;\)
注意到\(max(f[k])\)是前缀最大值 所以树状数组前缀维护最大值就行了

还有一种单调队列的做法
按照起点从左到右排序
每次看结尾有那些在指定区域内都加上
然后单调队列维护一下就行了
code:

//
#include<bits/stdc++.h>
using namespace std;
#define maxnn 200100
#define ll long long
#define GC getchar()
inline ll R() {
    char t;
    ll x=0;
    t=GC;
    while(!isdigit(t)) {
        t=GC;
    }
    while(isdigit(t)) {
        x=x*10+t-'0';
        t=GC;
    }
    return x;
}
ll f[maxnn];
ll n;
#define lowbit(i) i&(-i)
ll c[maxnn];
void add(ll x,ll d) {
    for(int i=x; i<=n+100100; i+=lowbit(i)) {
        c[i]=max(c[i],d);
    }
}
ll get(ll x) {
    ll ans=0;
    for(int i=x; i; i-=lowbit(i)) {
        ans=max(c[i],ans);
    }
    return ans;
}
struct node {
    ll fir,sec,v;
} a[maxnn];
bool cmp(node a,node b) {
    return a.sec<b.sec;
}
ll d[maxnn],cnt;
int main() {
    //freopen("water.in","r",stdin);
    //freopen("water.out","w",stdout);
    n=R();
    for(int i=1; i<=n; i++) {
        a[i].fir=R();
        a[i].sec=R();
        a[i].v=R();
        d[++cnt]=a[i].fir;
        d[++cnt]=a[i].sec;
    }
    sort(d+1,d+1+cnt);
    ll r=unique(d+1,d+1+cnt)-d;
    for(int i=1; i<=n; i++) {
        a[i].fir=lower_bound(d+1,d+r,a[i].fir)-d;
        a[i].sec=lower_bound(d+1,d+r,a[i].sec)-d;
    }
    sort(a+1,a+1+n,cmp);
    ll ans=0;
    for(int i=1; i<=n; i++) {
        f[a[i].sec]=max(f[a[i].sec],get(a[i].fir-1)+a[i].v);
        add(a[i].sec,f[a[i].sec]);
        ans=max(ans,f[a[i].sec]);
    }
    cout<<ans;
}

B 化学
时间限制 : - MS 空间限制 : - KB
评测说明 : 1s,256m

解:
折半搜索或者分段打表
然后我考试的时候以为对拍了就稳了 然后就没有静态差错更加没有看全数据范围 \(m ≤ 10^18\) \(1 ≤q≤ 10^18\)
上次考试也是这样 数据范围没有看 然后就想当然地以为对拍了就没有错 真是失智

看完题目一定要看数据范围 加亮标记 题目要读三遍!!! 最后检查的时候一定要看wan数据范围一定要静态查错....
附上代码:

//
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define maxnn 60
vector<ll> Q1,Q2;
ll n,m;
ll all1,all2;
ll e1[maxnn],e2[maxnn];
ll p[maxnn];
#define GC getchar()
inline ll R() {
    char t;
    ll x=0;
    t=GC;
    while(!isdigit(t)) {
        t=GC;
    }
    while(isdigit(t)) {
        x=x*10+t-'0';
        t=GC;
    }
    return x;
}
int main()
{
    //freopen("chemistry.in","r",stdin);
    //freopen("chemistry.out","w",stdout);
    n=R();m=R();
    for(int i=1;i<=n;i++)
    {
        p[i]=R();
    }
    ll d1=n/2;
    all1=(1LL<<d1)-1;
    ll d2=n-d1;
    all2=(1LL<<d2)-1;
    for(int i=1;i<=d1;i++)
    {
        e1[i]=p[i];
    }
    ll num=0;
    for(int i=d1+1;i<=n;i++)
    {
        e2[++num]=p[i];
    }
    for(int i=0;i<=all1;i++)
    {
        ll d=0;
        for(int j=1;j<=d1;j++)
        {
            if(i&(1<<j-1))
            {
                d+=e1[j];
            }
        }
        Q1.push_back(d);
    }
        for(int i=0;i<=all2;i++)
    {
        ll d=0;
        for(int j=1;j<=d2;j++)
        {
            if(i&(1<<j-1))
            {
                d+=e2[j];
            }
        }
        Q2.push_back(d);
    }
    sort(Q1.begin(),Q1.end());
    sort(Q2.begin(),Q2.end());
    ll ans=0;
    for(int i=0;i<Q1.size();i++)
    {
        int d=Q2.size();
        d--;
        if(Q2[d]<=(m-Q1[i])) {ans+=d+1;continue;}
        ans+=upper_bound(Q2.begin(),Q2.end(),m-Q1[i])-Q2.begin();
    }
    cout<<ans;
}

C 读书
时间限制 : - MS 空间限制 : - KB
评测说明 : 1s,256m

解:
贪心一下 考虑链就行了
code:

//
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxnn 1000010
int size[maxnn];
int T;
int n;
int f[maxnn][24];
#define GC getchar()
inline ll R() {
    char t;
    ll x=0;
    t=GC;
    while(!isdigit(t)) {
        t=GC;
    }
    while(isdigit(t)) {
        x=x*10+t-'0';
        t=GC;
    }
    return x;
}
int las[maxnn],en[maxnn],le[maxnn],tot,nex[maxnn];
int dep[maxnn];
void add(int a,int b) {
    en[++tot]=b;
    nex[tot]=las[a];
    las[a]=tot;
}
int goup(int x,int k) {
    int s=log2(n);
    for(int i=s; i>=0; i--) {
        if((1<<i)&k) {
            x=f[x][i];
        }
    }
    return x;
}
void dfs1(int v,int fa) {
    dep[v]=dep[fa]+1;
    f[v][0]=fa;
    size[v]=1;
    int s=log2(n);
    for(int i=1; i<=s; i++) {
        f[v][i]=f[f[v][i-1]][i-1];
    }
    for(int i=las[v]; i; i=nex[i]) {
        int u=en[i];
        if(u!=fa) {
            dfs1(u,v);
            size[v]+=size[u];
        }
    }
}
void clear()
{
    memset(las,0,sizeof(las));
    tot=0;
    memset(size,0,sizeof(size));
    memset(dep,0,sizeof(dep));
    memset(f,0,sizeof(f));
}
void FIE()
{
    freopen("book.in","r",stdin);
    freopen("book.out","w",stdout);
}
int main() {
    //FIE();
    T=R();
    while(T--) {
        clear();
        n=R();
        int x,y;
        for(int i=1; i<n; i++) {
            x=R();
            y=R();
            add(x,y);
            add(y,x);
        }
        dfs1(1,1);
        int tmp1=0;
        int tmp2=0;
        int d=(dep[n]-dep[1]-1)/2;
        int r=goup(n,d);
        tmp2=size[r];
        tmp1=n-size[r];
        puts(tmp1>tmp2?"^_^":"T_T");
    }
}

下次再不看数据范围我就》》》
不要以为对拍就没事 要静态查错注意数据范围

猜你喜欢

转载自www.cnblogs.com/OIEREDSION/p/11776229.html