acmore|acmore.cc1211采油区域1212会议中心1213抢掠计划APIO2009

采油区域:

#include <iostream>  
#include <algorithm>  
#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <cmath>  
#define M 1500+5  
#define inf 0x3f3f3f3f  
using namespace std;  
int s[M][M],zx[M][M],yx[M][M],zs[M][M],ys[M][M],a[M][M],h[M],l[M];  
int n,m,k;  
int Calc(int x,int y)  
{  
    return s[x][y]-s[x-k][y]-s[x][y-k]+s[x-k][y-k];  
}  
void Prepare()  
{  
    for (int i=0;i<=n+1;i++)  
        for (int j=0;j<=m+1;j++)  
            zx[i][j]=yx[i][j]=zs[i][j]=ys[i][j]=-inf;  
    for (int i=k;i<=n;i++)  
    {  
        for (int j=k;j<=m;j++)  
                yx[i][j]=max(max(yx[i][j-1],yx[i-1][j]),Calc(i,j));  
        for (int j=m-k+1;j;j--)  
                zx[i][j]=max(max(zx[i-1][j],zx[i][j+1]),Calc(i,j+k-1));  
    }  
    for (int i=n-k+1;i;i--)  
    {  
        for (int j=k;j<=m;j++)  
                ys[i][j]=max(max(ys[i][j-1],ys[i+1][j]),Calc(i+k-1,j));  
        for (int j=m-k+1;j;j--)  
                zs[i][j]=max(max(zs[i+1][j],zs[i][j+1]),Calc(i+k-1,j+k-1));  
    }  
    for (int i=k;i<=n;i++)  
    {  
        h[i]=-inf;  
        for (int j=k;j<=m;j++)  
            h[i]=max(h[i],Calc(i,j));  
    }  
    for (int i=k;i<=m;i++)  
    {  
        l[i]=-inf;  
        for (int j=k;j<=n;j++)  
            l[i]=max(l[i],Calc(j,i));  
    }  
}  
void Solve()  
{  
    int ans=0;  
    for (int i=k;i+k<=n;i++)  
    {  
        for (int j=i+k;j+k<=n;j++)  
            ans=max(ans,yx[i][m]+h[j]+ys[j+1][m]);  
        for (int j=k;j+k<=m;j++)  
            ans=max(ans,ys[i+1][m]+yx[i][j]+zx[i][j+1]),  
            ans=max(ans,yx[i][m]+ys[i+1][j]+zs[i+1][j+1]);  
    }  
    for (int i=k;i+k<=m;i++)  
    {  
        for (int j=i+k;j+k<=m;j++)  
            ans=max(ans,ys[1][i]+l[j]+zs[1][j+1]);  
        for (int j=k;j+k<=n;j++)  
            ans=max(ans,yx[j][i]+ys[j+1][i]+zs[1][i+1]),  
            ans=max(ans,ys[1][i]+zx[j][i+1]+zs[j+1][i+1]);  
    }  
    printf("%d\n",ans);  
}  
int main()  
{  
    scanf("%d%d%d",&n,&m,&k);  
    for (int i=1;i<=n;i++)  
        for (int j=1;j<=m;j++)  
            scanf("%d",&a[i][j]),s[i][j]=a[i][j]+s[i][j-1];  
    for (int i=2;i<=n;i++)  
        for (int j=1;j<=m;j++)  
            s[i][j]+=s[i-1][j];  
    Prepare();  
    Solve();  
    return 0;  
}  

会议中心:

#include <iostream>  
#include <stdio.h>  
#include <stdlib.h>  
#include <math.h>  
#include <algorithm>  
#include <string.h>  
#include <set>  
#define lch (c<<1)  
#define rch ((c<<1)|1)  
#define mid ((l+r)>>1)  
using namespace std;  
const int INF=1000000001;  
const int MAXN=200010;  
const int Pow[20]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144};  
   
int tr[MAXN<<3],delta[MAXN<<3],cnt;  
   
set<int> sl,sr;  
   
struct Num//lsh  
{  
    int num,pos;  
    friend bool operator <(Num a,Num b){return (a.num<b.num);}  
}N[MAXN<<1];  
   
struct line  
{  
    int l,r;  
    friend bool operator <(line a,line b)  
    {  
        if (a.r<b.r) return 1;  
        else if (a.r==b.r) return a.l>b.l;  
        return 0;  
    }  
}lt[MAXN],L[MAXN];  
   
int l[MAXN],r[MAXN],ll,rr,R[MAXN][20];  
   
inline void down(int c)  
{  
    if (!c) return;  
    if (delta[c]) tr[lch]=delta[lch]=tr[rch]=delta[rch]=1;  
    delta[c]=0;  
}  
   
void change(int c,int l,int r)  
{  
    tr[c]=1;  
    if (ll<=l&&r<=rr)  
    {  
        delta[c]=1;  
        return;  
    }  
    if (ll<=mid) change(lch,l,mid);  
    if (rr>mid) change(rch,mid+1,r);  
}  
   
bool query(int c,int l,int r)  
{  
    bool ans=0;  
    if (ll<=l&&r<=rr) return tr[c];  
    down(c);  
    if (ll<=mid) ans|=query(lch,l,mid);  
    if (rr>mid) ans|=query(rch,mid+1,r);  
    return ans;  
}  
   
int st(int x,int y)  
{  
    int i,l=1,r=cnt,ans=INF;  
    if (x>y) return 0;  
    while (l<=r)  
    {  
        if (L[mid].l>=x)  
        {  
            ans=mid;  
            r=mid-1;  
        }  
        else l=mid+1;  
    }  
    if (ans==INF) return 0;  
    x=ans;ans=0 ;  
    for (i=18;i>=0;--i)  
    {  
        if (R[x][i]!=-1&&L[R[x][i]].r<=y)  
        {  
            ans+=Pow[i-1];  
            if (i==0) ++ans;  
            x=R[x][i];  
        }  
    }  
    return ans;  
}  
   
void work()  
{  
    int i,j,k,num=0,last=-INF,n,ans,cnt1;  
    scanf("%d",&n);  
    for (i=1;i<=n;++i)  
    {  
        scanf("%d%d",l+i,r+i);  
        N[++num].num=l[i];  
        N[num].pos=num;  
        N[++num].num=r[i];  
        N[num].pos=num;  
    }  
    sort(N+1,N+1+num);//lsh  
    for (i=1;i<=num;++i)  
    {  
        if (last!=N[i].num)   
        {  
            ++cnt;  
            last=N[i].num;  
        }  
        if (N[i].pos&1) l[(N[i].pos>>1)+1]=cnt;  
        else r[N[i].pos>>1]=cnt;  
    }  
    cnt1=cnt;//cnt1 is maxnumber  
    for (i=1;i<=n;++i)  
    {  
        lt[i].l=l[i];  
        lt[i].r=r[i];  
    }  
    sort(lt+1,lt+1+n);  
    L[cnt=1]=lt[last=1];  
    for (i=2;i<=n;++i)  
    {  
        if (lt[i].l<=lt[last].l) continue;  
        L[++cnt]=lt[i];  
        last=i;  
    }  
    last=0;  
    for (i=1;i<=cnt;++i)  
    {  
        R[i][0]=i;  
        if (last!=-1)   
        {  
            for (j=last;j<=cnt&&L[i].r>=L[j].l;++j);  
            if (j>cnt) R[i][1]=last=-1;//-1 means no ans  
            else R[i][1]=last=j;  
        }  
        else R[i][1]=-1;  
    }  
    for (k=2;k<=18;++k)  
    {  
        for (i=1;i<=cnt;++i)  
        {  
            if (R[i][k-1]==-1) R[i][k]=-1;  
            else R[i][k]=R[R[i][k-1]][k-1];  
        }  
    }  
    printf("%d\n",ans=st(1,INF));  
    sl.insert(INF);//s1 left  
    sr.insert(0);//s2 right  
    for (i=1;i<=n;++i)  
    {  
        ll=l[i];rr=r[i];  
        if (query(1,1,cnt1)) continue;  
        if (st(-*sr.lower_bound(-l[i])+1,l[i]-1)+st(r[i]+1,*sl.upper_bound(r[i])-1)+1==st(-*sr.lower_bound(-l[i])+1,*sl.upper_bound(r[i])-1))  
        {  
            printf("%d ",i);  
            change(1,1,cnt1);  
            sl.insert(l[i]);  
            sr.insert(-r[i]);  
        }  
    }  
}  
   
int main()  
{  
    work();  
    return 0;  
}  

抢掠计划:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define inf 0x7fffffff
#define ll long long
using namespace std;
inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,S,p,tim,scc,top,cnt,ans;
int head[500005],h[500005],f[500005];
int belong[500005],v[500005];
int c[500005],dfn[500005],low[500005],q[500005];
bool inq[500005];
struct data{int to,next;}e[500005];
struct edge{int to,next;}ed[500005];
void insert(int u,int v)
{e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;}
void ins(int u,int v)
{ed[++cnt].to=v;ed[cnt].next=h[u];h[u]=cnt;}
void tarjan(int x)
{
    int now=0;
	dfn[x]=low[x]=++tim;
	q[++top]=x;inq[x]=1;
	for(int i=head[x];i;i=e[i].next)
	    if(!dfn[e[i].to]){tarjan(e[i].to);low[x]=min(low[x],low[e[i].to]);}
	    else if(inq[e[i].to])low[x]=min(low[x],dfn[e[i].to]);
	if(low[x]==dfn[x])
	{
		scc++;
	    while(now!=x)
	    {
		    now=q[top];top--;
		    belong[now]=scc; 
		    v[scc]+=c[now];
		    inq[now]=0;
	    }
	}
}
void rebuild()
{
     cnt=0;
     for(int i=1;i<=n;i++)
         for(int j=head[i];j;j=e[j].next)
             if(belong[i]!=belong[e[j].to])
				 ins(belong[i],belong[e[j].to]);
}
void spfa()
{
	int t=0,w=1;
	q[t]=belong[S];inq[belong[S]]=1;
	f[belong[S]]=v[belong[S]];
	while(t!=w)
	{
		int now=q[t];t++;if(t==500000)t=0;
     	for(int i=h[now];i;i=ed[i].next)
    	{
    		if(f[now]+v[ed[i].to]>f[ed[i].to])
    		{
    		    f[ed[i].to]=f[now]+v[ed[i].to];
    	    	if(!inq[ed[i].to])
				{inq[ed[i].to]=1;q[w++]=ed[i].to;if(w==500000)w=0;}
    	    }
    	}
    	inq[now]=0;
    }
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=m;i++)
	{
	    int u=read(),v=read();
	    insert(u,v);
	}
	for(int i=1;i<=n;i++)
	    c[i]=read();
	for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
	S=read();p=read();
	rebuild();
	spfa();
	for(int i=1;i<=p;i++)
	{
		int x=read();
		if(f[belong[x]]>ans)ans=f[belong[x]];
	}
	printf("%d",ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值