寻宝游戏

毒瘤题。

估计考试只会前30pts30pts30pts暴力然后果断走人。

正解是考虑到一个数&1\&1&1和∣0|0∣0都没有变化,&0\&0&0会强制变成000,∣1|1∣1会强制变成111,于是如果结果是111说明最后一个出现的∣1|1∣1在最后一个出现的&0\&0&0的后面,这样我们将所有的操作集合拿来搞成一个010101串并把所有010101串反向之后就可以求出可行范围然后得出答案了。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<1)+(ans<<3)+(ch^48),ch=getchar();
	return ans;
}
const int mod=1e9+7,N=5005;
int n,m,q,Bit[N],sum[N],c[2],rk[N],lastrk[N],l,r;
char s[N];
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline void update(int&a,const int&b){a=add(a,b);}
inline void init(){
	for(ri i=Bit[0]=1;i<=n;++i)Bit[i]=(Bit[i-1]<<1)%mod;
    for(ri i=1;i<=m;++i)rk[i]=i;
}
inline void Sort(){
    for(ri i=c[0]=c[1]=0;i<n;++i,c[0]=c[1]=0){
        scanf("%s",s+1);
        for(ri j=1;j<=m;++j)++c[s[j]^48],update(sum[j],(s[j]^48)*Bit[i]);
        c[1]+=c[0];
        for(ri j=m;j;--j)lastrk[c[s[rk[j]]^48]--]=rk[j];
		swap(lastrk,rk);
    }
}
int main(){
    n=read(),m=read(),q=read(),init(),Sort();
	while(q--){
        scanf("%s",s+1),l=0,r=m+1;
        for(ri i=1;i<=m;++i)if(s[rk[i]]^48){r=i;break;}
        for(ri i=m;i;--i)if(!(s[rk[i]]^48)){l=i;break;}
        l>=r?cout<<0<<'\n':cout<<(dec(r>m?Bit[n]:sum[rk[r]],sum[rk[l]]))<<'\n';
    }
	return 0;
}

转盘

考虑时间倒流转化问题:

想象成从TTT时刻开始每个时刻可以倒着走一步或者停住,每个物品有一个消失时间,要在所有物品消失之前经过它们。

为了方便我们断环为链

假设是从iii开始倒退(n≤i&lt;2n)(n\le i&lt;2n)(n≤i<2n),则有T−(i−j)≥tj⇒T≥(tj−j)+i⇒Tmin=max⁡{Tj−j}+iT-(i-j)\ge t_j\Rightarrow T\ge(t_j-j)+i\Rightarrow T_{min}=\max\{T_j-j\}+iT−(i−j)≥tj​⇒T≥(tj​−j)+i⇒Tmin​=max{Tj​−j}+i。

令ai=ti−ia_i=t_i-iai​=ti​−i

那么Ans=minn≤i&lt;2n{maxi−n&lt;j≤i{aj}+i}Ans=min_{n\le i&lt;2n}\{max_{i-n&lt;j\le i}\{a_j\}+i\}Ans=minn≤i<2n​{maxi−n<j≤i​{aj​}+i}

因为ai&gt;ai+n,i≤na_i&gt;a_{i+n},i\le nai​>ai+n​,i≤n

所以Ans=min1≤i≤n{maxi≤j≤2n{aj}+i}+n−1Ans=min_{1\le i\le n}\{max_{i\le j\le 2n}\{a_j\}+i\}+n-1Ans=min1≤i≤n​{maxi≤j≤2n​{aj​}+i}+n−1

然后发现就是唯一一个后缀maxmaxmax的minminmin,这个可以用线段树维护单调栈实现。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<1)+(ans<<3)+(ch^48),ch=getchar();
	return ans;
}
const int N=1e5+5,inf=0x3f3f3f3f;
int n,m,lastans,a[N<<1],type;
namespace SGT{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (T[p].l+T[p].r>>1)
	struct Node{int l,r,val,mx;}T[N<<3];
	inline int query(int p,int lim,int v){
		if(T[p].l==T[p].r)return min(T[p].l==lim?inf:T[p].l+1+v,T[p].l+max(v,T[p].mx));
		if(v>=T[rc].mx)return query(lc,lim,v);
		return min(T[p].val,query(rc,lim,v));
	}
	inline void pushup(int p){T[p].mx=max(T[lc].mx,T[rc].mx),T[p].val=query(lc,mid,T[rc].mx);}
	inline void build(int p,int l,int r){
		T[p].l=l,T[p].r=r;
		if(l==r){T[p].mx=a[l];return;}
		build(lc,l,mid),build(rc,mid+1,r),pushup(p);
	}
	inline void update(int p,int k,int v){
		if(T[p].l==T[p].r){T[p].mx=v;return;}
		update(k<=mid?lc:rc,k,v),pushup(p);
	}
	#undef lc
	#undef rc
	#undef mid
}
int main(){
  	n=read(),m=read(),type=read();
  	for(ri i=1;i<=n;++i)a[i]=read()-i,a[i+n]=a[i]-n;
  	SGT::build(1,1,n<<1);
  	cout<<(lastans=SGT::T[1].val+n-1)<<'\n';
  	for(ri x,y;m;--m){
  		x=read()^(type*lastans),y=read()^(type*lastans);
  		SGT::update(1,x,y-x),SGT::update(1,x+n,y-x-n);
		cout<<(lastans=SGT::T[1].val+n-1)<<'\n';
  	}
	return 0;
}

毒瘤

枚举边的状态+树形dpdpdp这种暴力757575应该都是一眼会吧。

但这样会TLETLETLE掉最后几个点 出题人毒瘤

然后需要建出这棵树的虚树来优化每次dpdpdp的时间。

然后就没了。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<1)+(ans<<3)+(ch^48),ch=getchar();
    return ans;
}
typedef pair<int,int> pii;
typedef long long ll;
const int N=1e5+5,mod=998244353;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
int P[N][2],n,m,ans=0,f[N][2],siz[N],tot=0,dfn[N];
vector<int>e[N];
vector<pii>G;
bool vis[N],key[N],ban[N][2];
void Dfs(int p,int fa){
    dfn[p]=++tot;
    for(ri i=0,v;i<e[p].size();++i){
        if((v=e[p][i])==fa)continue;
		if(dfn[v]){key[p]=1;if(dfn[p]<dfn[v])G.push_back(pii(p,v));continue;}
        else Dfs(v,p),siz[p]+=siz[v];
    }
    key[p]|=siz[p]>=2;
	siz[p]=siz[p]||key[p];
}
struct Coef{
	int x,y;
	Coef(int _x=0,int _y=0):x(_x),y(_y){}
	friend inline Coef operator+(const Coef&a,const Coef&b){return Coef(add(a.x,b.x),add(a.y,b.y));}
	friend inline Coef operator*(const Coef&a,const int&b){return Coef(mul(a.x,b),mul(a.y,b));}
}k[N][2];
struct Node{int v;Coef a,b;};
vector<Node>E[N];
inline int Build(int p){
	P[p][0]=P[p][1]=vis[p]=1;
	int ret=0;
	for(ri w,i=0,v;i<e[p].size();++i){
		if(vis[v=e[p][i]])continue;
		w=Build(v);
		if(!w)P[p][1]=mul(P[p][1],P[v][0]),P[p][0]=mul(P[p][0],add(P[v][0],P[v][1]));
		else if(key[p])E[p].push_back((Node){w,k[v][0]+k[v][1],k[v][0]});
		else k[p][0]=k[v][0]+k[v][1],k[p][1]=k[v][0],ret=w;
	}
	if(key[p])k[p][0]=Coef(1,0),k[p][1]=Coef(0,1),ret=p;
	else k[p][0]=k[p][0]*P[p][0],k[p][1]=k[p][1]*P[p][1];
	return ret;
}
inline void solve(int p){
	f[p][0]=ban[p][0]?0:P[p][0];
	f[p][1]=ban[p][1]?0:P[p][1];
	for(ri i=0,v;i<E[p].size();++i){
		solve((v=E[p][i].v));
		f[p][0]=mul(f[p][0],add(mul(E[p][i].a.x,f[v][0]),mul(E[p][i].a.y,f[v][1])));
		f[p][1]=mul(f[p][1],add(mul(E[p][i].b.x,f[v][0]),mul(E[p][i].b.y,f[v][1])));
	}
}
inline void init(int sta){
    for(ri i=0,x,y,tmp;i<G.size();++i){
        tmp=(sta>>i)&1,x=G[i].fi,y=G[i].se;
        if(!tmp)ban[x][1]=1;
        else ban[x][0]=ban[y][1]=1;
    }
    solve(1),ans=add(ans,add(f[1][0],f[1][1]));
    for(ri i=0,x,y,tmp;i<G.size();++i){
        tmp=(sta>>i)&1,x=G[i].fi,y=G[i].se;
        if(!tmp)ban[x][1]=0;
        else ban[x][0]=ban[y][1]=0;
    }
}
int main(){
  	n=read(),m=read();
  	for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
	Dfs(1,0),key[1]=1,Build(1);
  	for(ri sta=0,up=1<<G.size();sta<up;++sta)init(sta);
  	cout<<ans;
    return 0;
}

游戏

对于两个可以不能相通的块,如果钥匙在左边,那么可能可以从左到右但并不能从右到左,我们对于这种情况建一条有向边,然后动态维护一个拓扑排序即可。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=1e6+5;
int n,m,q,goa[N],l[N],r[N],mp[N],du[N],tot=0,x,y;
vector<int>e[N];
inline void add(const int&u,const int&v){e[u].push_back(v),++du[v];}
inline void extend(int i){
	static int t1,t2;
	while(1){
        t1=l[i]^1,t2=r[i]^n;
        if(t1)(!goa[l[i]-1])||(goa[l[i]-1]>=l[i]&&goa[l[i]-1]<=r[i])?l[i]=l[mp[l[i]-1]]:t1=0;
        if(t2)(!goa[r[i]])||(goa[r[i]]>=l[i]&&goa[r[i]]<=r[i])?r[i]=r[mp[r[i]+1]]:t2=0;
        if(!(t1+t2))break;
    }
}
inline void topsort(){
	static int q[N],hd,tl;
	hd=1,tl=0;
    for(ri i=1;i<=n;i++)if(mp[i]==i&&!du[i])q[++tl]=i;
    while(hd<=tl){
        int p=q[hd++];
		extend(p);
		for(ri i=0,v;i<e[p].size();++i)if(!(--du[v=e[p][i]]))q[++tl]=v;
    }
}
int main(){
    n=read(),m=read(),q=read();
    for(ri i=1;i<=n;i++)mp[i]=l[i]=r[i]=i;
    while(m--)x=read(),goa[x]=read();
    for(ri i=1;i<=n;i++)if(!goa[i])mp[i+1]=mp[i];else goa[i]<=i?add(mp[i+1],mp[i]):add(mp[i],mp[i+1]);
    for(ri i=1;i<=n;i++)l[mp[i]]=min(l[mp[i]],l[i]),r[mp[i]]=max(r[mp[i]],r[i]);
    topsort();
    for(ri i=1;i<=n;i++)l[i]=l[mp[i]],r[i]=r[mp[i]];
    while(q--)x=read(),y=read(),puts(l[x]<=y&&y<=r[x]?"YES":"NO");
    return 0;
}

排列

考虑按照题意建边建出来是一棵外向树。

然后显然应该按某一种拓扑序来形成序列(注意这个时候要判环来看是否合法)

这个东西可以用并查集+堆来搞一下,比较的依据是一个连通块的平均权值。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<1)+(ans<<3)+(ch^48),ch=getchar();
    return ans;
}
const int N=5e5+5;
typedef long long ll;
typedef pair<long double,int> pii;
int n,m,siz[N],fa[N],anc[N];
ll w[N],ans=0;
inline int find(const int&x){return x^anc[x]?anc[x]=find(anc[x]):x;}
struct In_Out_queue{
	priority_queue<pii,vector<pii>,greater<pii> >a,b;
	inline void push(const pii&x){a.push(x);}
	inline void del(const pii&x){b.push(x);}
	inline pii top(){while(b.size()&&a.top()==b.top())a.pop(),b.pop();return a.top();}
	inline void pop(){while(b.size()&&a.top()==b.top())a.pop(),b.pop();a.pop();}
}q;
int main(){
	n=read();
	for(ri i=0;i<=n;++i)anc[i]=i;
	for(ri i=1;i<=n;++i){
		fa[i]=read();
		if(anc[find(i)]^anc[find(fa[i])])anc[find(i)]=find(fa[i]);
		else return puts("-1"),0;
	}
	ll ans=0;
	anc[0]=0;
	for(ri i=1;i<=n;++i)ans+=(w[i]=read()),anc[i]=i,siz[i]=1,q.push(pii((long double)w[i],i));
	for(ri i=1;i<=n;++i){
		int x=q.top().se,y=find(fa[x]);
		q.pop();
		if(y)q.del(pii((long double)w[y]/siz[y],y));
		ans+=(ll)siz[y]*w[x],siz[y]+=siz[x],anc[x]=y,w[y]+=w[x];
		if(y)q.push(pii((long double)w[y]/siz[y],y));
	}
	cout<<ans;
    return 0;
}

道路

HNOI2018最水的一道没有之一没错就是它。 并不是反话

由于题目中给了深度保证,于是直接暴力三维树形dpdpdp就能过了。

记忆化搜索真的好写

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
inline int read(){
    int ans=0;
    bool f=1;
    char ch=getchar();
    while(!isdigit(ch))f^=ch=='-',ch=getchar();
    while(isdigit(ch))ans=(ans<<1)+(ans<<3)+(ch^48),ch=getchar();
    return f?ans:-ans;
}
const int N=20005;
ll a[N],b[N],c[N],f[N][45][45];
int son[N][2],n;
ll dfs(int p,int x,int y){
	if(p>=n)return c[p-n+1]*(a[p-n+1]+x)*(b[p-n+1]+y);
	if(f[p][x][y]^f[0][0][0])return f[p][x][y];
	return f[p][x][y]=min(dfs(son[p][0],x,y)+dfs(son[p][1],x,y+1),dfs(son[p][0],x+1,y)+dfs(son[p][1],x,y));
}
int main(){
	n=read();
	memset(f,127,sizeof(f));
	for(ri i=1,x,y;i<n;++i){
		x=read(),y=read();
		if(x<0)x=n-x-1;
		if(y<0)y=n-y-1;
		son[i][0]=x,son[i][1]=y;
	}
	for(ri i=1;i<=n;++i)a[i]=read(),b[i]=read(),c[i]=read();
	return cout<<dfs(1,0,0),0;
}

HNOI 2018 简要题解的更多相关文章

  1. JXOI 2018 简要题解

    目录 「JXOI2018」游戏 题意 题解 代码 「JXOI2018」守卫 题意 题解 代码 「JXOI2018」排序问题 题意 题解 代码 总结 「JXOI2018」游戏 题意 可怜公司有 \(n\ ...

  2. NOIP 2018 简要题解

    从这里开始 Day 1 Problem A 考虑贪心地选取极大非 0 段减少. 如果两次操作有交,并且不是包含关系,那么把其中一次操作的,但另一次没有操作的移过去,然后就变成了上面那个贪心了. Cod ...

  3. codechef February Challenge 2018 简要题解

    比赛链接:https://www.codechef.com/FEB18,题面和提交记录是公开的,这里就不再贴了 Chef And His Characters 模拟题 Chef And The Pat ...

  4. HNOI2019 简要题解

    HNOI 2019 简要题解 没想到自己竟也能有机会写下这篇题解呢. LOJ Luogu Day1T1 鱼 枚举\(AD\)两点后发现\(BC\)与\(EF\)相对独立,因此只需要计算合法的\(BC\ ...

  5. Tsinghua 2018 DSA PA2简要题解

    反正没时间写,先把简要题解(嘴巴A题)都给他写了记录一下. upd:任务倒是完成了,我也自闭了. CST2018 2-1 Meteorites: 乘法版的石子合并,堆 + 高精度. 写起来有点烦貌似. ...

  6. HNOI2018简要题解

    HNOI2018简要题解 D1T1 寻宝游戏 题意 某大学每年都会有一次 Mystery Hunt 的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得这一年出题的机会. 作为 ...

  7. CQOI2018简要题解

    CQOI2018简要题解 D1T1 破解 D-H 协议 题意 Diffie-Hellman 密钥交换协议是一种简单有效的密钥交换方法.它可以让通讯双方在没有事先约定密钥(密码)的情况下,通过不安全的信 ...

  8. A · F · O —— JLOI2018翻车记(附Day1简要题解)

    JLOI2018翻车记 并不知道该怎么写... 算了还是按照标准剧情来吧 这应该是一篇写得非常差的流水账... 2018.04.04 Day -1 省选前在机房的最后一天. 压力并不是很大,毕竟联赛 ...

  9. Noip 2014酱油记+简要题解

    好吧,day2T1把d默认为1也是醉了,现在只能期待数据弱然后怒卡一等线吧QAQ Day0 第一次下午出发啊真是不错,才2小时左右就到了233,在车上把sao和fate补掉就到了= = 然后到宾馆之后 ...

随机推荐

  1. servlet cdi analysis

    CDI中最令人兴奋的功能是允许每个人在Java EE平台中编写强大的扩展性功能,甚至于改变其核心本身.这些扩展性功能是可以完全移植到任何支持CDI的环境中. CDI的一些主要特性 1.类型安全:CDI ...

  2. superrvisor application config ini

    1. zookeeper [program:zookeeper] environment = JAVA_HOME="/opt/jdk1.8.0_191" process_name= ...

  3. centos 支持安装libsodium

    yum install epel-release -y yum install libsodium -y 然后没了.

  4. Java虚拟机------JVM介绍

    Java平台和语言最开始只是SUN公司在1990年12月开始研究的一个内部项目: Java的平台无关性 Java平台和语言最开始只是SUN公司在1990年12月开始研究的一个内部项目[stealth ...

  5. POJ1003 – Hangover (基础)

    Hangover   Description How far can you make a stack of cards overhang a table? If you have one card, ...

  6. 性能测试day07_性能瓶颈和分析

    其实如果之前都做的很到位的话,那么再加上APM工具(dynaTrace等),监控到非常细节,那么我们跑一个业务,我们就能完全清楚的知道每个请求的时间,也能知道请求所产生sql的时间,这样你自然而然都知 ...

  7. BZOJ 4872 luogu P3750 [六省联考2017]分手是祝愿

    4872: [Shoi2017]分手是祝愿 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description ...

  8. Linux实操篇 vi和vim编辑器

    vi和vim的基本介绍 所有的Linux系统都会内建vi文本编辑器. vim具有程序编辑的能力,可以看做是vi的增强版本,可以主动的以字体颜色辨别语法的正确性,方便程序设计.代码补完.编译及错误跳转等 ...

  9. http-cookie、session、Token

    无状态  cookie技术的发展 客户端发送请求登录系统 Set-Cookie管理Cookie信息并且返回给客户端 拿着返回的cookie请求Server cookie 管理session 发送登录信 ...

  10. block引用外部变量原理

    block在赋值时才会生成对应的block结构体实例(结构体数据结构在编译时已经生成),赋值时会扫一遍里面引用的外部变量(嵌套block中的外部变量也算,只不过嵌套block中的外部变量会被内外两个b ...