zoukankan      html  css  js  c++  java
  • POI2015选做

    感谢(darkbzoj)的倾情赞助

    以下题目不是按照难度顺序进行排序

    bzoj4386

    推荐完成:luogu4159

    假设边权全部为(1)怎么做?

    一般是直接快速幂,方便统计答案我们让所有点向一个虚拟汇点连边,这个虚拟汇点再连一个自环,接下来直接倍增即可

    但是这里的边权是(1-3),于是按照上题的思路考虑拆点,将点(u)拆成((u,0),(u,1),(u,2)),每一条边可以看做是((u,w))连向((v,0))

    代码如下

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define fir first
    #define sec second
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define maxd 1000000007
    #define eps 1e-6
    typedef long long ll;
    const int N=100000;
    const double pi=acos(-1.0);
    struct matrix{
    	ll x[130][130];
    }bin[70];
    int n,m;ll k;
    matrix operator *(matrix a,matrix b)
    {
    	matrix c;
    	rep(i,0,n*3)
    		rep(j,0,n*3) c.x[i][j]=0; 
    	rep(i,0,n*3)
    	{
    		rep(j,0,n*3)
    		{
    			rep(k,0,n*3) c.x[i][j]+=a.x[i][k]*b.x[k][j];
    		}
    	}
    	return c;
    }
    
    int calc(matrix a)
    {
    	ll tmp=0;
    	rep(i,1,n)
    	{
    		if (tmp>=k-(a.x[i][0]-1)) return 1;
    		tmp+=a.x[i][0]-1;
    	}
    	return 0;
    }
    
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    	while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    	return x*f;
    }
    
    int main()
    {
    	n=read();m=read();scanf("%lld",&k);
    	bin[0].x[0][0]=1;
    	rep(i,1,n)
    	{
    		bin[0].x[i][0]=1;
    		bin[0].x[i][i+n]=1;
    		bin[0].x[i+n][i+n+n]=1;
    	}
    	rep(i,1,m)
    	{
    		int u=read(),v=read(),w=read();
    		bin[0].x[u+(w-1)*n][v]++;
    	}
    	int pos,flag=0;
    	rep(i,1,64)
    	{
    		bin[i]=bin[i-1]*bin[i-1];
    		if (calc(bin[i])) {pos=i-1;flag=1;break;}
    	}
    	if (!flag) {puts("-1");return 0;}
    	ll ans=0;
    	matrix tmp,now;
    	rep(i,1,n) now.x[i][i]=1; 
    	per(i,pos,0)
    	{
    		tmp=now*bin[i];
    		if (!calc(tmp)) {now=tmp;ans+=(1ll<<i);}
    	}
    	printf("%lld",ans);
    	return 0;
    } 
    

    bzoj4380

    对于第一问,我们进行区间(dp),记(dp_{l,r,i})表示在区间([l,r])中的最小值为(k)时的最大收益,那么肯定是要将读入的(c_i)全部离散化的,并且在这里只考虑在([l,r])中的人的需求

    接下来考虑转移,直接枚举最小值(k)的位置,有(dp_{l,r,i}=max(dp_{l,pos-1,c_1}+dp_{pos+1,r,c_2}+g_{pos,i}*cost_i)),其中(c_1geq i,c_2geq i)(g_{pos,i})表示包含(pos)(cgeq i)的区间数

    方便转移,我们再记(f_{l,r,i}=max(dp_{l,r,j})(jgeq i)),于是方程的前两项可以直接用(f)代替

    对于第二问输出方案,我们记录每次转移(dp)的值的时候的决策点(pos),直接(dfs)即可

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define fir first
    #define sec second
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define maxd 1000000007
    #define eps 1e-6
    typedef long long ll;
    const int N=100000;
    const double pi=acos(-1.0);
    int n,m,x[10010],siz,dp[60][60][4100],f[60][60][4100],g[60][4100],
    	pos[60][60][4100],ans[4100];
    struct node{
    	int l,r,c;
    }p[4100];
    
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    	while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    	return x*f;
    }
    
    void dfs(int l,int r,int k)
    {
    	if (l>r) return;
    	if (!f[l][r][k])
    	{
    		rep(i,l,r) ans[i]=x[k];
    		return;
    	}
    	rep(i,k,siz)
    	{
    		if (dp[l][r][i]==f[l][r][k])
    		{
    			int now=pos[l][r][i];
    			ans[now]=x[i];
    			dfs(l,now-1,i);
    			dfs(now+1,r,i);
    			break;
    		}
    	}
    }
    
    int main()
    {
    	n=read();m=read();
    	rep(i,1,m)
    	{
    		p[i].l=read();p[i].r=read();p[i].c=read();
    		x[i]=p[i].c;
    	}
    	sort(x+1,x+1+m);
    	siz=unique(x+1,x+1+m)-x-1;
    	rep(i,1,m) p[i].c=lower_bound(x+1,x+1+siz,p[i].c)-x;
    	per(l,n,1)
    	{
    		rep(r,l,n)
    		{
    			rep(i,l,r)
    				rep(j,1,siz) g[i][j]=0;
    			rep(i,1,m)
    			{
    				if ((p[i].l>=l) && (p[i].r<=r))
    					rep(j,p[i].l,p[i].r) g[j][p[i].c]++;
    			}
    			rep(i,l,r)
    				per(j,siz-1,0) g[i][j]+=g[i][j+1];
    			rep(i,l,r)
    			{
    				per(j,siz,1)
    				{
    					int tmp=f[l][i-1][j]+f[i+1][r][j]+g[i][j]*x[j];
    					if (dp[l][r][j]<tmp) {pos[l][r][j]=i;dp[l][r][j]=tmp;}
    					f[l][r][j]=max(f[l][r][j+1],dp[l][r][j]);
    				}
    			}
    		}
    	}
    	dfs(1,n,1);
    	printf("%d
    ",f[1][n][1]);
    	rep(i,1,n) printf("%d ",ans[i]);
    	return 0;
    }
    

    bzoj3747

    枚举左端点,同时选取合适的右端点,更新答案

    可以将问题转化成为最大子段和问题,具体的,对于第一次出现的位置,对答案的贡献为(w_i),第二次出现时贡献为(-w_i)(为了与之前的抵消),这之后都是(0),每一次暴力修改

    辣鸡bzoj卡我空间

    // luogu-judger-enable-o2
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define lowbit(x) (x)&(-x)
    #define fir first
    #define sec second
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define maxd 1000000007
    typedef long long ll;
    const int N=100000;
    const double pi=acos(-1.0);
    struct node{
        ll sum,maxl,maxr,maxsum;
    }seg[4004000];
    int n,m,f[1001000],w[1001000],pos[1001000],len[1001000];
    vector<int> kind[1001000];
    
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    void pushup(int id)
    {
        seg[id].sum=seg[id<<1].sum+seg[id<<1|1].sum;
        seg[id].maxl=max(seg[id<<1].maxl,seg[id<<1|1].maxl+seg[id<<1].sum);
        seg[id].maxr=max(seg[id<<1|1].maxr,seg[id<<1].maxr+seg[id<<1|1].sum);
        seg[id].maxsum=max(max(seg[id<<1].maxsum,seg[id<<1|1].maxsum),seg[id<<1].maxr+seg[id<<1|1].maxl);
    }
    
    void modify(int id,int l,int r,int pos,int val)
    {
        //cout << id << " " << l << " " << r << " " << pos << " " << val << endl;
        //system("pause");
        if (l==r)
        {
            seg[id].sum=val;seg[id].maxl=val;
            seg[id].maxr=val;seg[id].maxsum=val;
            return;
        }
        int mid=(l+r)>>1;
        if (pos<=mid) modify(id<<1,l,mid,pos,val);
        else modify(id<<1|1,mid+1,r,pos,val);
        pushup(id);
    }
    
    void out(int id,int l,int r)
    {
        if (l==r) 
        {
            cout << seg[id].sum << " ";
            return;
        }
        int mid=(l+r)>>1;
        out(id<<1,l,mid);out(id<<1|1,mid+1,r);
    }
    
    int main()
    {
        n=read();m=read();
        rep(i,1,n)
        {
            f[i]=read();len[f[i]]++;
            kind[f[i]].push_back(i);
        }
        rep(i,1,m) w[i]=read();
        rep(i,1,m)
        {
            if (len[i]>=1) modify(1,1,n,kind[i][0],w[i]);
            if (len[i]>=2) modify(1,1,n,kind[i][1],-w[i]);
        }
        ll ans=0;
        rep(i,1,n)
        {
            ans=max(ans,seg[1].maxsum);
            modify(1,1,n,i,0);
            pos[f[i]]++;
            if (pos[f[i]]<len[f[i]]) modify(1,1,n,kind[f[i]][pos[f[i]]],w[f[i]]);
            if (pos[f[i]]+1<len[f[i]]) modify(1,1,n,kind[f[i]][pos[f[i]]+1],-w[f[i]]);
        }
        printf("%lld",ans);
        return 0;
    }
    

    bzoj4378

    对于(geq s)的数,它们可以在每一次操作中出现,记一共有(x)个这样的数,那么还剩下(c-x)个空位

    对于(<s)的数,每一个数(a_i)可以看成是(a_i)个大小为(1)的物体放入(s)个大小为(c-x)的抽屉中,询问是否放的满

    (sum=sum_{a_i<s}a_i),那么必须有(sumgeq (c-x)*s)

    两个树状数组维护,一个维护([1,x])之间有多少个数,另一个维护([1,x])之间的数的和

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define int long long
    #define lowbit(x) (x)&(-x)
    #define fir first
    #define sec second
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define maxd 1000000007
    typedef long long ll;
    const int N=100000;
    const double pi=acos(-1.0);
    struct qnode{
        int op,x,y;
    }q[1001000];
    int n,siz,x[1001000],a[1001000],m;
    char op[100];
    struct BIT{
        ll t[2000100];
        
        void add(int pos,int val)
        {
            int i;
            for (i=pos;i<=siz;i+=lowbit(i)) t[i]+=val;
        }
        
        ll query(int pos)
        {
            int i;ll ans=0;
            for (i=pos;i;i-=lowbit(i)) ans+=t[i];
            return ans;
        }
    }c1,c2;
    
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    signed main()
    {
        n=read();m=read();
        rep(i,1,m)
        {
            scanf("%s",op);
            q[i].x=read();q[i].y=read();
            if (op[0]=='U') q[i].op=0;else q[i].op=1;
            x[i]=q[i].y;
        }
        sort(x+1,x+1+m);
        siz=unique(x+1,x+1+m)-x-1;
        rep(i,1,m)
        {
            q[i].y=lower_bound(x+1,x+1+siz,q[i].y)-x;
            if (!q[i].op)
            {
                if (a[q[i].x]>0) 
                    {c1.add(a[q[i].x],-1);c2.add(a[q[i].x],-x[a[q[i].x]]);}
                c1.add(q[i].y,1);c2.add(q[i].y,x[q[i].y]);
                a[q[i].x]=q[i].y;
            }
            else
            {
                int cnt=c1.query(siz)-c1.query(q[i].y-1);
                ll sum=c2.query(q[i].y-1);
                if (sum>=((ll)q[i].x-cnt)*x[q[i].y]) puts("TAK");else puts("NIE");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    【bzoj4399】魔法少女LJJ 并查集+权值线段树合并
    【bzoj4059】[Cerc2012]Non-boring sequences 分治
    【bzoj4390】[Usaco2015 dec]Max Flow LCA
    【bzoj4127】Abs 树链剖分+线段树
    【bzoj1222】[HNOI2001]产品加工 背包dp
    【bzoj4966】总统选举 随机化+线段树
    protected internal == internal
    框架的一点小随笔
    WPF 的 数据源属性 和 数据源
    Python 运算符重载
  • 原文地址:https://www.cnblogs.com/encodetalker/p/10823194.html
Copyright © 2011-2022 走看看