zoukankan      html  css  js  c++  java
  • 20201003校测

    不要问我为什么今天写昨天的校测

    T1

    description:

    有N道判断题(题号编号为0~N-1),已知每道题的答案((0/1))以及答对后能获得的分数。同时还有M个额外分数。
    具体而言,每个额外分数给出四个参数(k) (i) (type) (pt)
    表示对于所有题号(j)满足(jequiv i(mod 2^k))的题目,如果这些题都选择(type(0/1)),那么会获得(pt)的额外分数

    data range;

    (N是2的整数次幂且N<=2^{20})
    (M<=10^6)

    solution:

    考虑如何维护那些奇怪的额外分数
    有一个很巧妙的方法:
    由低位向高位建01Trie,然后树上的每一个节点就恰好对应题目中的“额外分数”
    具体来讲,01Trie中深度为d,走到此处值为num就代表这些数除以(2^d)余num
    然后就是一个简单的树形dp了
    (f_{pos,0})表示pos子树内的题目全部选0可以获得的最大价值,类似定义(f_{pos,1})
    同时记(f_{pos,2})表示pos子树内的题目任意选择可以获得的最大价值
    那么就有如下转移:
    (f_{pos,0}=f_{lc,0}+f_{rc,0}+ex_{pos,0})
    (f_{pos,1}=f_{lc,1}+f_{rc,1}+ex_{pos,1})
    (f_{pos,2}=max(f_{lc,2}+f_{rc,2},f_{pos,0},f_{pos,1}))
    其中lc,rc分别表示pos的左右儿子,ex表示题目描述中的额外分数

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=(1<<20)+5;
    int n,st[N],a[N],m;
    struct _01Trie
    {
    	int dep,ch[N*21][2],tot;
    	ll f[N*21][3],ex[N*21][2];
    	void build(int pos,int d,int num)
    	{
    		if(d==dep){f[pos][2]=f[pos][st[num]]=a[num];return;}
    		ch[pos][0]=++tot;
    		build(ch[pos][0],d+1,num);
    		ch[pos][1]=++tot;
    		build(ch[pos][1],d+1,num+(1<<d));
    	}
    	inline void work()
    	{
    		dep=log2(n);
    		tot=1;build(1,0,0);
    	}
    	void upd(int pos,int nd,int d,int num,int tp,int val)
    	{
    		if(nd==d){ex[pos][tp]+=1ll*val;return;}
    		if(num&(1<<nd))upd(ch[pos][1],nd+1,d,num,tp,val);
    		else upd(ch[pos][0],nd+1,d,num,tp,val);
    	}
    	void solve(int pos,int d)
    	{
    		if(d==dep)return;
    		solve(ch[pos][0],d+1),solve(ch[pos][1],d+1);
    		f[pos][0]=f[ch[pos][0]][0]+f[ch[pos][1]][0]+ex[pos][0];
    		f[pos][1]=f[ch[pos][0]][1]+f[ch[pos][1]][1]+ex[pos][1];
    		f[pos][2]=max(f[ch[pos][0]][2]+f[ch[pos][1]][2],max(f[pos][0],f[pos][1]));
    	}
    }T;
    int main()
    {
    	scanf("%d",&n);
    	for(int i=0;i<n;++i)scanf("%d",st+i);
    	for(int i=0;i<n;++i)scanf("%d",a+i);
    	T.work();
    	scanf("%d",&m);
    	while(m--)
    	{
    		int k,i,typ,pt;scanf("%d%d%d%d",&k,&i,&typ,&pt);
    		T.upd(1,0,k,i,typ,pt);
    	}
    	T.solve(1,0);
    	printf("%lld
    ",T.f[1][2]);
    	return 0;
    }
    

    T2

    网络流(不会)

    T3

    description:

    一个(N*M)棋盘中已知每一行的棋子个数(a_i),求出在所有可能的棋局中,棋子数不少于k个的列数最少是多少

    data range;

    (N<=2*10^5) (M<=10^8)

    solution:

    考虑二分答案mid判断其是否可行
    我们尽量把前mid列全部填满,然后对于剩下的m-mid列,直接上抽屉原理
    具体来说mid值是可行的当且仅当((k-1)*(m-mid)>=x)
    其中x表示总棋子个数减去前mid列尽量填的个数(即剩下的)
    观察到(x=sum_{a_i>=mid}(a_i-mid)=sum_{a_i>=mid}a_i-mid*sum_{a_i>=mid}1)
    于是我们可以将a_i从小到大排序然后预处理后缀和check时lower_bound就可以了
    这样做的时间复杂度(O(nlog^2n))
    其实还可以再优化一点
    发现这个东西似乎和[NOI Online #1 提高组]冒泡排序里的柿子十分相似
    于是我们可以用动态开点的权值线段树类似地维护

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=2e5+5,LOG=20;
    int root,n,m,a[N];
    struct SGT
    {
    	int tot,lc[N*LOG],rc[N*LOG],c[N*LOG];LL s[N*LOG];
    	inline void up(int rt){s[rt]=s[lc[rt]]+s[rc[rt]],c[rt]=c[lc[rt]]+c[rc[rt]];}
    	void upd(int &rt,int l,int r,int p)
    	{
    		if(!rt)rt=++tot;
    		if(l==r){++c[rt],s[rt]+=1ll*l;return;}
    		int mid=(l+r)>>1;
    		if(p<=mid)upd(lc[rt],l,mid,p);
    		else upd(rc[rt],mid+1,r,p);
    		up(rt);
    	}
    	int solve(int rt,int l,int r,int k,LL sum,int cnt)
    	{
    	//	if(!rt)return 0;
    		if(l==r)return l;
    		int mid=(l+r)>>1;
    		if(sum+s[rc[rt]]-1ll*(cnt+c[rc[rt]])*mid<=1ll*(m-mid)*(k-1))
    			return solve(lc[rt],l,mid,k,sum+s[rc[rt]],cnt+c[rc[rt]]);
    		else return solve(rc[rt],mid+1,r,k,sum,cnt);
    	}
    }T;
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)scanf("%d",a+i);
    	for(int i=1;i<=n;++i)T.upd(root,0,m,a[i]);
    	for(int i=1;i<=n;++i)printf("%d ",T.solve(root,0,m,i,0,0));
    	return 0;
    }
    
  • 相关阅读:
    【转】VS2010中 C++创建DLL图解
    [转]error: 'retainCount' is unavailable: not available in automatic reference counting mode
    [转]关于NSAutoreleasePool' is unavailable: not available in automatic reference counting mode的解决方法
    【转】 Tomcat v7.0 Server at localhost was unable to start within 45
    【转】Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If
    【转】SVN管理多个项目版本库
    【转】eclipse安装SVN插件的两种方法
    【转】MYSQL启用日志,和查看日志
    【转】Repository has not been enabled to accept revision propchanges
    【转】SVN库的迁移
  • 原文地址:https://www.cnblogs.com/zmyzmy/p/13767595.html
Copyright © 2011-2022 走看看