JSOI2014

B 宅男计划

题面:bzoj
题解:三分+贪心
可以发现一个显然的性质
就是你买外卖的次数和你能维持的天数大概是成一个单峰函数证明不会
于是我们三分峰值
然后找到这个次数后再贪心
首先把那些又贵又放不久的扔掉,可以用单调栈
然后从最便宜的开始往上贪心
code

C 骑士游戏

题面:bzoj
题解:最短路?
可以显然的写出一个dp方程,然而你会发现会有环
我们发现这个方程的形式和spfa的转移形式差不多
所以把所有点扔到队列里,初值设置魔法攻击的代价,跑最短路
如果这个点被更新了,则反图上与它相连的点都有可能更新,入队
codeC

F 奇怪的计算器

题面:bzoj
题解:线段树
首先将这些值,因为不管怎么样都不会改变他们的大小关系
区间修改,如果最小的值小于下界就直接推平,上界同理
codeF

G 支线剧情2

题面:bzoj
题解:树形dp
设\(f[i]\)表示这个点有存档,之后都不存档的最少代价
\[f[u]=\sum_{(u,v,w)\in E}{f[v]+siz[v]*w}\]
设\(dp[u]\)表示这个点子树内有存档的最小代价
如果当前点存档,儿子也有一个存档则\(dp[u]+=dp[v]+deep[v]\),\(deep\)为从1到这个点的距离
否则直接转移(就是枚举一个最小值)
codeG

I 强连通图

题面:bzoj
题解:缩点
直接缩点就可以了
codeI

J 歌剧表演

题面:bzoj
题解:
用set维护不能分辨出来的一群人,相当于染色
具体看代码吧
codeJ

M 电信网络

题面:bzoj
题解:最大权闭合子图
codeM

O 序列维护

题面:bzoj
题解:线段树
区间加法,区间乘法
codeO

B code

#include<bits/stdc++.h>
using namespace std;
#define file(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout);
template<typename T>
inline void read(T& x)
{
    x=0;char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
#define maxn 205
#define ll long long
struct Food
{
    ll v,t;
    inline friend bool operator < (Food a,Food b)
        {
            return a.t<b.t;
        }
}a[maxn],sta[maxn];
int n,top;
ll m,f;
inline ll get(ll x)
{
    ll left=m-f*x,times=0,days=0,last;//剩余钱数,总天数,一次的天数,这一次买的东西能支持的天数
    if(left<0) return 0;
    for(int i=1;i<=n;++i)
    {
        last=min(a[i].t-days,left/(x*a[i].v));
        days+=last,times+=x*last,left-=last*x*a[i].v;
        if(days<a[i].t)//如果还是小于,则left那一项不够了(相当于没有买够这一项),就直接全买这一项
        {
            times+=left/a[i].v;
            break;
        }
    }
    return times;
}
int main()
{
    read(m),read(f),read(n);
    for(int i=1;i<=n;++i) read(a[i].v),read(a[i].t),++a[i].t;
    sort(a+1,a+n+1);
    for(int i=1;i<=n;++i)
    {
        while(top&&a[i].v<=sta[top].v) --top;
        sta[++top]=a[i];
    }
    n=top;
    for(int i=1;i<=n;++i) a[i]=sta[i];
    ll l=1,r=m/f+1,lm,rm,ans=0,ans1,ans2;
    while(l<=r)
    {
        lm=(l+l+r)/3,rm=(l+r+r)/3;
        ans1=get(lm),ans2=get(rm);
        if(ans1<ans2) l=lm+1,ans=max(ans,ans2);
        else r=rm-1,ans=max(ans,ans1);
    }
    if(l>1) ans=max(ans,get(l-1));//我的三分似乎有点锅,要把左右也算一下
    ans=max(ans,get(l+1));
    printf("%lld\n",ans);
    return 0;
}

top

C code

#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void read(T& x)
{
    x=0;char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
#define maxn 2000005
#define ll long long
struct Edge
{
    int fr,to;
}eg[maxn],eg_rev[maxn];
int head[maxn],head_rev[maxn],edgenum,vis[maxn],n;
inline void add(int fr,int to)
{
    eg[++edgenum]=(Edge){head[fr],to};
    eg_rev[edgenum]=(Edge){head_rev[to],fr};
    head[fr]=head_rev[to]=edgenum;
}
ll dis[maxn],s[maxn];
void spfa()
{
    queue<int> q;
    for(int i=1;i<=n;++i) q.push(i),vis[i]=1;
    while(!q.empty())
    {
        int id=q.front();
        q.pop(),vis[id]=0;
        ll res=s[id];
        for(int i=head[id];i;i=eg[i].fr)
            res+=dis[eg[i].to];
        if(res<dis[id])
        {
            dis[id]=res;
            for(int i=head_rev[id];i;i=eg_rev[i].fr)
                if(!vis[eg_rev[i].to]) vis[eg_rev[i].to]=1,q.push(eg_rev[i].to);
        }
    }
}
int main()
{
    read(n);
    int tp,num;
    for(int i=1;i<=n;++i)
    {
        read(s[i]),read(dis[i]),read(num);
        for(int j=1;j<=num;++j) read(tp),add(i,tp);
    }
    spfa();
    printf("%lld\n",dis[1]);
    return 0;
}

top

F code

#include<bits/stdc++.h>
using namespace std;
#define file(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout);
template<typename T>
inline void read(T& x)
{
    x=0;char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
#define maxn 200005
#define ll long long
struct OP
{
    int type;ll val;
}q[maxn];
pair<int,int> a[maxn];
struct Node
{
    int l,r;
    ll ptag,mtag,ptag2,mn,mx;
}t[maxn<<2];
#define ls rt<<1
#define rs rt<<1|1
ll L,R,ans[maxn];
inline void pushup(const int& rt)
{
    t[rt].mx=t[rs].mx,t[rt].mn=t[ls].mn;
}
inline void modify(const int& rt,const ll& ptag,const ll& ptag2,const ll& mtag)
{
    t[rt].mtag*=mtag,t[rt].ptag=t[rt].ptag*mtag+ptag,t[rt].ptag2=t[rt].ptag2*mtag+ptag2;
    t[rt].mn=t[rt].mn*mtag+a[t[rt].l].first*ptag2+ptag;
    t[rt].mx=t[rt].mx*mtag+a[t[rt].r].first*ptag2+ptag;
}
inline void pushdown(const int& rt)
{
    modify(ls,t[rt].ptag,t[rt].ptag2,t[rt].mtag);
    modify(rs,t[rt].ptag,t[rt].ptag2,t[rt].mtag);
    t[rt].ptag=t[rt].ptag2=0,t[rt].mtag=1;
}
void build(const int& rt,const int& l,const int& r)
{
    t[rt].mtag=1,t[rt].l=l,t[rt].r=r;
    if(l==r)
    {
        t[rt].mx=t[rt].mn=a[l].first;
        return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(rt);
}
void pushmin(const int& rt)
{
    if(t[rt].l==t[rt].r) return modify(rt,L,0,0);
    pushdown(rt);
    if(t[rs].mn<L) modify(ls,L,0,0),pushmin(rs);
    else pushmin(ls);
    pushup(rt);
}
void pushmax(const int& rt)
{
    if(t[rt].l==t[rt].r) return modify(rt,R,0,0);
    pushdown(rt);
    if(t[ls].mx>R) modify(rs,R,0,0),pushmax(ls);
    else pushmax(rs);
    pushup(rt);
}
void dfs(const int& rt)
{
    if(t[rt].l==t[rt].r)
    {
        ans[a[t[rt].l].second]=t[rt].mn;
        return;
    }
    pushdown(rt);
    dfs(ls),dfs(rs);
}
int id[256];
int main()
{
    //file("test");
    int n,m;char op[2];
    id['+']=0,id['-']=1,id['*']=2,id['@']=3;
    read(n),read(L),read(R);
    for(int i=1;i<=n;++i)
    {
        scanf("%s",op);
        q[i].type=id[op[0]],read(q[i].val);
    }
    read(m);
    for(int i=1;i<=m;++i) read(a[i].first),a[i].second=i;
    sort(a+1,a+m+1);
    build(1,1,m);
    for(int i=1;i<=n;++i)
    {
        if(q[i].type==0) modify(1,q[i].val,0,1);
        else if(q[i].type==1) modify(1,-q[i].val,0,1);
        else if(q[i].type==2) modify(1,0,0,q[i].val);
        else modify(1,0,q[i].val,1);
        if(t[1].mn<L) pushmin(1);
        if(t[1].mx>R) pushmax(1);
    }
    dfs(1);
    for(int i=1;i<=m;++i) printf("%lld\n",ans[i]);
    return 0;
}

top

G code

#include<bits/stdc++.h>
using namespace std;
#define file(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout);
inline void read(int& x)
{
    x=0;char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
#define maxn 1000005
#define ll long long
struct Edge
{
    int fr,to,val;
}eg[maxn<<1];
int head[maxn],edgenum;
inline void add(int fr,int to,int val)
{
    eg[++edgenum]=(Edge){head[fr],to,val};
    head[fr]=edgenum;
}
ll f[maxn],dp[maxn],siz[maxn];
void dfs(int rt,ll dis)
{
    if(!head[rt])
    {
        siz[rt]=1;
        return;
    }
    ll tmp=0;
    for(int i=head[rt];i;i=eg[i].fr)
    {
        dfs(eg[i].to,eg[i].val+dis);
        siz[rt]+=siz[eg[i].to];
        f[rt]+=f[eg[i].to]+1ll*siz[eg[i].to]*eg[i].val;
        tmp+=min(f[eg[i].to]+1ll*siz[eg[i].to]*eg[i].val,dp[eg[i].to]+dis+eg[i].val);
    }
    dp[rt]=f[rt];
    for(int i=head[rt];i;i=eg[i].fr)
        dp[rt]=min(dp[rt],tmp-min(f[eg[i].to]+1ll*siz[eg[i].to]*eg[i].val,dp[eg[i].to]+dis+eg[i].val)+dp[eg[i].to]+eg[i].val);
}
int main()
{
    int n,k,a,b;
    read(n);
    for(int i=1;i<=n;++i)
    {
        read(k);
        for(int j=1;j<=k;++j)
            read(a),read(b),add(i,a,b);
    }
    dfs(1,0);
    printf("%lld\n",dp[1]);
    return 0;
}

top

I code

#include<bits/stdc++.h>
using namespace std;
#define file(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout);
inline void read(int& x)
{
    x=0;char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
#define maxn 1000005
struct Edge
{
    int fr,to;
}eg[maxn<<1];
int head[maxn],edgenum;
inline void add(int fr,int to)
{
    eg[++edgenum]=(Edge){head[fr],to};
    head[fr]=edgenum;
}
int vis[maxn],dfn[maxn],low[maxn],dfn_clock,col[maxn],siz,colnum,ans;
int invis[maxn],outvis[maxn];
stack<int> s;
void Tarjan(int rt)
{
    low[rt]=dfn[rt]=++dfn_clock;
    s.push(rt);
    vis[rt]=1;
    for(int i=head[rt];i;i=eg[i].fr)
    {
#define to eg[i].to
        if(!dfn[to]) Tarjan(to),low[rt]=min(low[rt],low[to]);
        else if(vis[to]) low[rt]=min(low[rt],dfn[to]);
#undef to
    }
    if(low[rt]==dfn[rt])
    {
        ++colnum;
        siz=0;
        while(s.top()!=rt)
        {
            int tp=s.top();
            s.pop();
            col[tp]=colnum;
            ++siz;
            vis[tp]=0;
        }
        s.pop();
        col[rt]=colnum;
        ++siz;
        vis[rt]=0;
        ans=max(ans,siz);
    }
}
int main()
{
    int n,m,x,y;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i) scanf("%d%d",&x,&y),add(x,y);
    for(int i=1;i<=n;++i)
        if(!dfn[i]) Tarjan(i);
    printf("%d\n",ans);
    for(int i=1;i<=n;++i)
        for(int j=head[i];j;j=eg[j].fr)
            if(col[i]!=col[eg[j].to])
                invis[col[eg[j].to]]=1,outvis[col[i]]=1;
    int indeg=0,outdeg=0;
    for(int i=1;i<=colnum;++i)
    {
        if(!invis[i]) ++indeg;
        if(!outvis[i]) ++outdeg;
    }
    printf("%d\n",max(indeg,outdeg));//注意不要特判0(我也不知道为什么)
    return 0;
}

top

J code

#include<bits/stdc++.h>
using namespace std;
inline void read(int& x)
{
    x = 0; char c = getchar();
    while (!isdigit(c)) c = getchar();
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
}
#define maxn 100005
set<int> s[maxn];
int a[maxn], col[maxn], ans[maxn], cnt, n, m;
inline bool cmp(int a, int b)
{
    return col[a] < col[b];
}
int main()
{
    read(n), read(m);
    int k;
    for (int i = 1; i <= n; ++i) s[0].insert(i);
    for (int i = 1; i <= m; ++i)
    {
        read(k);
        for (int j = 1; j <= k; ++j) read(a[j]);
        sort(a + 1, a + k + 1, cmp);
        for (int l = 1, r; l <= k; l = r + 1)
        {
            r = l;
            while (r < k && col[a[r + 1]] == col[a[l]]) ++r;
            if (s[col[a[l]]].size() == r - l + 1) continue;
            int now = col[a[l]]; ++cnt;
            for (int j = l; j <= r; ++j)
                s[now].erase(a[j]), col[a[j]] = cnt, s[cnt].insert(a[j]);
            if (s[now].size() == 1 && !ans[*s[now].begin()])
                ans[*s[now].begin()] = i;
            if (s[cnt].size() == 1 && !ans[*s[cnt].begin()])
                ans[*s[cnt].begin()] = i;
        }
    }
    for (int i = 1; i <= n; ++i) printf("%d ", ans[i]);
    //for (int i = 1; i <= n; ++i) printf("%d%c", ans[i], "\n"[i == n]);
    return 0;
}

top

M code

#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void read(T& x)
{
    x=0;char c=getchar();int f=1;
    while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
    x*=f;
}
#define maxn 505
#define inf 0x3f3f3f3f
struct Edge
{
    int fr,to,val;
}eg[maxn*maxn*2];
int head[maxn],edgenum=1,n,m;
inline void add(int fr,int to,int val)
{
    eg[++edgenum]=(Edge){head[fr],to,val};
    head[fr]=edgenum;
}
int deep[maxn],gap[maxn],cur[maxn],s,t,maxflow;
void bfs()
{
    queue<int> q;
    for(int i=0;i<=n;++i) deep[i]=-1,gap[i]=0;
    deep[t]=0;gap[0]=1;
    q.push(t);
    while(!q.empty())
    {
        int tmp=q.front();q.pop();
        for(int i=head[tmp];i;i=eg[i].fr)
            if(deep[eg[i].to]==-1)
            {
                q.push(eg[i].to);
                deep[eg[i].to]=deep[tmp]+1;
                ++gap[deep[eg[i].to]];
            }
    }
}
int dfs(int now,int flow)
{
    if(now==t)
    {
        maxflow+=flow;
        return flow;
    }
    int tmpflow=0,used=0;
    for(int i=cur[now];i;i=eg[i].fr)
    {
        cur[now]=i;
        if(deep[now]==deep[eg[i].to]+1&&eg[i].val)
        {
            if(tmpflow=dfs(eg[i].to,min(flow-used,eg[i].val)))
            {
                used+=tmpflow;
                eg[i].val-=tmpflow;
                eg[i^1].val+=tmpflow;
            }
            if(used==flow) return used;
        }
    }
    if(!--gap[deep[now]]) deep[s]=n+1;
    ++gap[++deep[now]];
    return used;
}
void ISAP()
{
    bfs();
    while(deep[s]<n) memcpy(cur,head,sizeof(head)),dfs(s,0x3f3f3f3f);
}
struct Node
{
    int x,y,r,v;
}o[maxn];
inline int dis(Node a,Node b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int main()
{
    read(n);
    s=0,t=n+1;
    for(int i=1;i<=n;++i)
        read(o[i].x),read(o[i].y),read(o[i].r),read(o[i].v);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
        {
            if(i==j) continue;
            if(dis(o[i],o[j])<=o[i].r*o[i].r) add(i,j,inf),add(j,i,0);
        }
    int ans=0;
    for(int i=1;i<=n;++i)
    {
        if(o[i].v>0) add(s,i,o[i].v),add(i,s,0),ans+=o[i].v;
        else add(i,t,-o[i].v),add(t,i,0);
    }
    ISAP();
    printf("%d\n",ans-maxflow);
    return 0;
}

top

O code

#include<bits/stdc++.h>
using namespace std;
#define file(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout);
template<typename T>
inline void read(T& x)
{
    x=0;char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
#define maxn 200005
#define ll long long
struct Node
{
    int l,r;
    ll val,ptag,mtag;
}t[maxn<<2];
#define ls rt<<1
#define rs rt<<1|1
ll p,a[maxn];
inline void pushup(const int& rt)
{
    t[rt].val=(t[ls].val+t[rs].val)%p;
}
inline int len(const int& rt)
{
    return t[rt].r-t[rt].l+1;
}
inline void modify(int rt,ll ptag,ll mtag)
{
    if(ptag==0&&mtag==1) return;
    t[rt].val=(t[rt].val*mtag+ptag*len(rt))%p;
    t[rt].ptag=(t[rt].ptag*mtag+ptag)%p;
    t[rt].mtag=t[rt].mtag*mtag%p;
}
inline void pushdown(const int& rt)
{
    if(t[rt].ptag==0&&t[rt].mtag==1) return;
    modify(ls,t[rt].ptag,t[rt].mtag);
    modify(rs,t[rt].ptag,t[rt].mtag);
    t[rt].ptag=0,t[rt].mtag=1;
}
inline void build(int rt,int l,int r)
{
    t[rt].mtag=1,t[rt].l=l,t[rt].r=r;
    if(l==r)
    {
        t[rt].val=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(rt);
}
inline void update(int rt,int l,int r,int fr,int to,ll ptag,ll mtag)
{
    if(fr<=l&&to>=r) return modify(rt,ptag,mtag);
    int mid=(l+r)>>1;
    pushdown(rt);
    if(fr<=mid) update(ls,l,mid,fr,to,ptag,mtag);
    if(to>mid) update(rs,mid+1,r,fr,to,ptag,mtag);
    pushup(rt);
}
inline ll query(int rt,int l,int r,int fr,int to)
{
    if(fr<=l&&to>=r) return t[rt].val;
    int mid=(l+r)>>1;ll ans=0;
    pushdown(rt);
    if(fr<=mid) ans=query(ls,l,mid,fr,to);
    if(to>mid) ans+=query(rs,mid+1,r,fr,to);
    return ans%p;
}
inline void print(int n)
{
    for(int i=1;i<=n;++i) printf("%lld ",query(1,1,n,i,i));
    puts(" ");
}
int main()
{
    //file("test");
    int n,m;
    read(n),read(p);
    for(int i=1;i<=n;++i) read(a[i]),a[i]%=p;
    build(1,1,n);
    read(m);
    int op,x,y,z;
    for(int i=1;i<=m;++i)
    {
        read(op),read(x),read(y);
        if(op==3) printf("%lld\n",query(1,1,n,x,y));
        else read(z),update(1,1,n,x,y,op==2?z:0,op==1?z:1);
    }
    return 0;
}

top

原文地址:https://www.cnblogs.com/123789456ye/p/12262816.html

时间: 2024-10-22 11:52:07

JSOI2014的相关文章

美梦1(JSOI2014,算法艺术与信息学竞赛)

[问题描述] 这天晚上,约翰做了个奇怪的美梦.他拥有了分别分布在N座高高低低的山上的N个池塘,N座山连成一条直线,从左往右第i座山的高度是Hi.池塘中的鱼都是他请专家运用科学的方法专门养殖的,为了保护每个池塘的生态环境,他现在要在这N座山上建造若干个看护点.约翰是个很节约的人,在第i座山建造看护点的花费为Ci.假设在第i座山建造一个看护点,则往左或者往右第一座不比这座山低的山将挡住看护的视线.譬如说: {Hi} = {1 4 4 5 7 2}表示第一座山高度为1,第二座山高度为4... 如果在第

【BZOJ5037】[Jsoi2014]电信网络 最大权闭合图

[BZOJ5037][Jsoi2014]电信网络 Description JYY创建的电信公司,垄断着整个JSOI王国的电信网络.JYY在JSOI王国里建造了很多的通信基站.目前所有的基站都是使用2G网络系统的.而现在3G时代已经到来了,JYY在思考,要不要把一些基站升级成3G网络的呢?JSOI王国可以被看作为一个无穷大的二维平面,JYY一共建造了N个通信基站,第i个基站的坐标是(Xi,Yi).每个基站有一个通信范围Ri.第i号基站会向所有到其距离不超过Ri的基站发送信息.每个基站升级到3G网络

bzoj3876 [Ahoi2014&amp;Jsoi2014]支线剧情

3876: [Ahoi2014&Jsoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2180  Solved: 1300[Submit][Status][Discuss] Description [故事背景] 宅男JYY非常喜欢玩RPG游戏,比如仙剑,轩辕剑等等.不过JYY喜欢的并不是战斗场景,而是类似电视剧一般的充满恩怨情仇的剧情.这些游戏往往 都有很多的支线剧情,现在JYY想花费最少的时间看完所有的支线剧情. [问题描述

[luogu] P4040 [AHOI2014/JSOI2014]宅男计划(贪心)

P4040 [AHOI2014/JSOI2014]宅男计划 题目背景 自从迷上了拼图,JYY就变成了个彻底的宅男.为了解决温饱问题,JYY不得不依靠叫外卖来维持生计. 题目描述 外卖店一共有N种食物,分别有1到N编号.第i种食物有固定的价钱Pi和保质期Si.第i种食物会在Si天后过期.JYY是不会吃过期食物的. 比如JYY如果今天点了一份保质期为1天的食物,那么JYY必须在今天或者明天把这个食物吃掉,否则这个食物就再也不能吃了.保质期可以为0天,这样这份食物就必须在购买当天吃掉. JYY现在有M

「JSOI2014」序列维护

「JSOI2014」序列维护 传送门 其实这题就是luogu的模板线段树2,之所以要发题解就是因为被 \(\color{black}{\text{M}} \color{red}{\text{_sea}}\) 告知了一种比较NB的 \(\text{update}\) 的方式. 我们可以把修改操作统一化,视为 \(ax + b\) 的形式,然后我们按照原来的套路来维护两个标记,分别代表 \(a\) 和 \(b\) ,那么我们的更新就可以这么写: inline void f(int p, int at

「JSOI2014」强连通图

「JSOI2014」强连通图 传送门 第一问很显然就是最大的强连通分量的大小. 对于第二问,我们先把原图进行缩点,得到 \(\text{DAG}\) 后,统计出入度为零的点的个数和出度为零的点的个数,两者取 \(\max\) 就是答案. 理性证明可以看这里 参考代码: #include <cstdio> #define rg register #define file(x) freopen(x".in", "r", stdin), freopen(x&q

「AHOI2014/JSOI2014」骑士游戏

「AHOI2014/JSOI2014」骑士游戏 传送门 考虑 \(\text{DP}\). 设 \(dp_i\) 表示灭种(雾)一只编号为 \(i\) 的怪物的代价. 那么转移显然是: \[dp_i = \min(K_i, S_i + \sum_{j = 1}^{R_i} dp_{v_j})\] 但是我们会发现这个东西是有后效性的... 所以我们会想要用建图然后跑一个最短路什么的来搞... 于是我们观察到上面那个 \(\text{DP}\) 式子中,\(dp_i\) 如果用后面那一项来转移,显然

「AHOI2014/JSOI2014」支线剧情

「AHOI2014/JSOI2014」支线剧情 传送门 上下界网络流. 以 \(1\) 号节点为源点 \(s\) ,新建一个汇点 \(t\),如果 \(u\) 能到 \(v\),那么连边 \(u \to v\),下界为 \(1\),上界为 \(+\infty\),费用为对应的所需时间,表示这段剧情至少看一次,且看一次代价为对应的所需时间. 又因为我们可以在任何一个节点重开一次,所以我们的每个节点 \(u\) 都连边 \(u \to t\) ,下界为 \(0\),上界为 \(+\infty\),费

「AHOI2014/JSOI2014」拼图

「AHOI2014/JSOI2014」拼图 传送门 看到 \(n \times m \le 10^5\) ,考虑根号分治. 对于 \(n < m\) 的情况,我们可以枚举最终矩形的上下边界 \(tp, bt\),那么我们发现最终矩形一定是由所有满足从第 \(tp\) 行到第 \(bt\) 行都是白格子的矩形顺次连接,并且两端再各自接上一个最大的前缀和一个最大的后缀构成的. 这个我们可以 \(O(m)\) 地算. 总复杂度就是 \(O(n^2m)\),也就是一个根号级别的. 对于 \(n \ge

「JSOI2014」学生选课

「JSOI2014」学生选课 传送门 看到这题首先可以二分. 考虑对于当前的 \(mid\) 如何 \(\text{check}\) 我们用 \(f_{i,j}\) 来表示 \(i\) 对 \(j\) 的好感度排名,那么对于两个人 \(i\),\(j\) 如果有 \(\max\{f_{i, j}, f_{j, i}\} > mid\) 那么显然这两个人是不能上同一个老师的课的. 而且每个人可以上的课只有两种,我们记为 \(a_{i, 0 / 1}\) 假设 \(i\),\(j\) 对于当前的 \