高一上七月下旬日记

7.21

闲话

  • 以为体活食堂能早点开门,遂睡到 \(6:25\) 就起来去食堂了,结果 \(6:40\) 才开门。到机房刷脸打卡的时候是 \(7:00:43\) 左右。
  • 上午 \(7:30 \sim 11:30\) @Delov 学长安排了一场模拟赛。
  • 模拟赛打到一半被 \(field\) 叫回宿舍整改内务,说 \(huge\) 已经在宿舍等我们了。“放风”一半发现 \(feifei\) 也从后面追来了,遂跑着回到宿舍整改内务。走的时候 \(huge\) 说以后集训就按今天的标准,下周领导视察很多,别出问题。
  • 午休 \(huge\) 查宿。
  • 下午 \(huge\) 来说了今年国赛的情况,说了下 \(NOI\) 向类 \(IOI\) 赛制转变对 \(HZOI\) 的影响;举了 @APJifengc 的例子; \(D\) 了下他们模拟赛遇到比较难写的题选择口胡而不写代码,说早期几届学长经常写一些码量比较大的题,但现在选择写这种题的人越来越少了。
  • 晚上加赛。
  • 晚休 \(field\) 查宿。

做题纪要

CF685B Kay and Snowflake

  • 对于每组询问遍历一遍整棵子树不可接受。

  • 接着考虑重心的一些性质。

    • \(x\) 为根的子树的重心一定在以 \(x\) 的所有子节点为根的子树的重心到 \(x\) 的路径上。
  • 求出重心后暴力向上跳即可。

    点击查看代码
    struct node
    {
    	int nxt,to;
    }e[600010];
    int head[600010],siz[600010],weight[600010],ans[600010],fa[600010],cnt=0;
    void add(int u,int v)
    {
    	cnt++;
    	e[cnt].nxt=head[u];
    	e[cnt].to=v;
    	head[u]=cnt;
    }
    void dfs(int x,int father)
    {
    	siz[x]=1;
    	fa[x]=father;
    	weight[x]=0;
    	ans[x]=x;
    	for(int i=head[x];i!=0;i=e[i].nxt)
    	{
    		if(e[i].to!=father)
    		{
    			dfs(e[i].to,x);
    			siz[x]+=siz[e[i].to];
    			weight[x]=max(weight[x],siz[e[i].to]);
    		}
    	}
    	for(int i=head[x];i!=0;i=e[i].nxt)
    	{
    		int y=ans[e[i].to];
    		while(y!=x)
    		{
    			if(max(weight[y],siz[x]-siz[y])<=siz[x]/2)
    			{
    				ans[x]=y;
    				break;
    			}
    			else
    			{
    				y=fa[y];
    			}
    		}
    	}
    }
    int main()
    {
    	int n,m,u,v,i;
    	cin>>n>>m;
    	for(i=2;i<=n;i++)
    	{
    		cin>>u;
    		v=i;
    		add(u,v);
    	}
    	dfs(1,0);
    	for(i=1;i<=m;i++)
    	{
    		cin>>u;
    		cout<<ans[u]<<endl;
    	}
    	return 0;
    }
    

CF958C3 Encryption (hard)

[ARC148C] Lights Out on Tree

[ARC153C] ± Increasing Sequence

luogu P2056 [ZJOI2007] 捉迷藏

7.22

闲话

  • 上午 @worldvanquisher 讲了 \(BSGS\)\(Prüfer\) 序 列,莫反,拉格朗日插值; @Chen_jr 讲了基环树。原容斥被换成了拉格朗日插值。

做题纪要

CF958C2 Encryption (medium)

  • 多倍经验: CF958C1 Encryption (easy)

  • CF958C3 Encryption (hard) ,取使 \(f_{h,j-1}\) 取到最大值的 \(h\) 即可。

    点击查看代码
    ll a[500010],sum[500010],f[500010][2];
    int main()
    {
    	ll n,k,p,maxx,pos,i,j;
    	scanf("%lld%lld%lld",&n,&k,&p);
    	for(i=1;i<=n;i++)
    	{
    		scanf("%lld",&a[i]);
    		sum[i]=sum[i-1]+a[i];
    	}
    	f[0][0]=0;
    	for(j=1;j<=k;j++)
    	{
    		maxx=f[j-1][(j-1)&1];
    		pos=j-1; 
    		for(i=j;i<=n;i++)
    		{
    			f[i][j&1]=f[pos][(j-1)&1]+(sum[i]-sum[pos])%p;
    			if(f[i][(j-1)&1]>maxx)
    			{
    				maxx=f[i][(j-1)&1];
    				pos=i;
    			}
    		}
    	} 
    	printf("%lld\n",f[n][k&1]);
    	return 0;
    }
    

P145 修仙(restart)

luogu P2617 Dynamic Rankings

  • 树状数组套主席树板子。
    • 每次修改都会对后续操作产生影响,对主席树进行暴力修改时空复杂度均不能接受。考虑树状数组来维护变化的过程。
    • 树状数组的每一个节点都是一颗主席树(叫做动态开点权值线段树可能更合适)。
    • 操作中的修改就能转化成单点修改,查询时将设计到的树状数组的节点提出来进行询问。
      • 若将原树的点也看做修改操作,时空复杂度为 \(O((n+m)\log^{2} n)\)

        点击查看代码
        struct ask
        {
        	int l,r,k;
        	char pd;
        }q[200010];
        int a[200010],b[200010];
        struct PDS_SMT
        {
        	int root[200010],rt_sum=0;
        	struct SegmentTrew
        	{
        		int ls,rs,sum;
        	}tree[200010<<8];
        	#define lson(rt) tree[rt].ls
        	#define rson(rt) tree[rt].rs
        	int build_rt()
        	{
        		rt_sum++;
        		return rt_sum;
        	}
        	void build_tree(int &rt,int l,int r)
        	{
        		rt=build_rt();
        		if(l==r)
        		{
        			return;
        		}
        		int mid=(l+r)/2;
        		build_tree(lson(rt),l,mid);
        		build_tree(rson(rt),mid+1,r);
        	}
        	void update(int &rt,int l,int r,int pos,int val)
        	{
        		rt=(rt==0)?build_rt():rt;
        		tree[rt].sum+=val;
        		if(l==r)
        		{
        			return;
        		}
        		int mid=(l+r)/2;
        		if(pos<=mid)
        		{
        			update(lson(rt),l,mid,pos,val);
        		}
        		else
        		{
        			update(rson(rt),mid+1,r,pos,val);
        		}
        	}
        	int query(int rt1[],int len1,int rt2[],int len2,int l,int r,int k)
        	{
        		if(l==r)
        		{
        			return l;
        		}
        		int mid=(l+r)/2,sum=0;
        		for(int i=1;i<=len2;i++)
        		{
        			sum+=tree[lson(rt2[i])].sum;
        		}
        		for(int i=1;i<=len1;i++)
        		{
        			sum-=tree[lson(rt1[i])].sum;
        		}
        		if(k<=sum)
        		{
        			for(int i=1;i<=len2;i++)
        			{
        				rt2[i]=lson(rt2[i]);
        			}
        			for(int i=1;i<=len1;i++)
        			{
        				rt1[i]=lson(rt1[i]);
        			}   
        			return query(rt1,len1,rt2,len2,l,mid,k);
        		}
        		else
        		{
        			for(int i=1;i<=len2;i++)
        			{
        				rt2[i]=rson(rt2[i]);
        			}
        			for(int i=1;i<=len1;i++)
        			{
        				rt1[i]=rson(rt1[i]);
        			}   
        			return query(rt1,len1,rt2,len2,mid+1,r,k-sum);
        		}
        	}
        }T;
        struct BIT
        {
        	int rt[2][32];
        	int lowbit(int x)
        	{
        		return (x&(-x));
        	}
        	void add(int n,int x,int val)
        	{
        		int pos=lower_bound(b+1,b+1+b[0],a[x])-b;
        		for(int i=x;i<=n;i+=lowbit(i))
        		{
        			T.update(T.root[i],1,b[0],pos,val);
        		}
        	}
        	int query(int l,int r,int k)
        	{
        		memset(rt,0,sizeof(rt));
        		for(int i=r;i>=1;i-=lowbit(i))
        		{
        			rt[1][0]++;
        			rt[1][rt[1][0]]=T.root[i];
        		}
        		for(int i=l-1;i>=1;i-=lowbit(i))
        		{
        			rt[0][0]++;
        			rt[0][rt[0][0]]=T.root[i];
        		}
        		return T.query(rt[0],rt[0][0],rt[1],rt[1][0],1,b[0],k);
        	}
        }B;
        int main()
        {
        	int n,m,i;
        	cin>>n>>m;
        	for(i=1;i<=n;i++)
        	{
        		cin>>a[i];
        		b[0]++;
        		b[b[0]]=a[i];
        	}
        	for(i=1;i<=m;i++)
        	{
        		cin>>q[i].pd>>q[i].l>>q[i].r;
        		if(q[i].pd=='Q')
        		{
        			cin>>q[i].k;
        		}
        		else
        		{
        			b[0]++;
        			b[b[0]]=q[i].r;
        		}
        	}
        	sort(b+1,b+1+b[0]);
        	b[0]=unique(b+1,b+1+b[0])-(b+1);
        	for(i=1;i<=n;i++)
        	{
        		B.add(n,i,1);
        	}
        	for(i=1;i<=m;i++)
        	{
        		if(q[i].pd=='Q')
        		{
        			cout<<b[B.query(q[i].l,q[i].r,q[i].k)]<<endl;
        		}
        		else
        		{
        			B.add(n,q[i].l,-1);
        			a[q[i].l]=q[i].r;
        			B.add(n,q[i].l,1);
        		}
        	}
        	return 0;
        }
        
      • 不将原树的点看做修改操作,开始时建立一棵静态主席树,查询时把主席树也提出来进行询问,时空复杂度为 \(O(n \log n+m \log^{2} n)\)

        点击查看代码
        struct ask
        {
        	int l,r,k;
        	char pd;
        }q[200010];
        int a[200010],b[200010];
        struct PDS_SMT
        {
        	int root1[200010],root2[200010],rt_sum=0;
        	struct SegmentTrew
        	{
        		int ls,rs,sum;
        	}tree[200010<<5];
        	#define lson(rt) tree[rt].ls
        	#define rson(rt) tree[rt].rs
        	int build_rt()
        	{
        		rt_sum++;
        		return rt_sum;
        	}
        	void build_tree(int &rt,int l,int r)
        	{
        		rt=build_rt();
        		if(l==r)
        		{
        			return;
        		}
        		int mid=(l+r)/2;
        		build_tree(lson(rt),l,mid);
        		build_tree(rson(rt),mid+1,r);
        	}
        	void update1(int pre,int &rt,int l,int r,int pos)
        	{
        		rt=build_rt();
        		tree[rt]=tree[pre];
        		tree[rt].sum++;
        		if(l==r)
        		{
        			return;
        		}
        		int mid=(l+r)/2;
        		if(pos<=mid)
        		{
        			update1(lson(pre),lson(rt),l,mid,pos);
        		}
        		else
        		{
        			update1(rson(pre),rson(rt),mid+1,r,pos);
        		}
        	}
        	void update2(int &rt,int l,int r,int pos,int val)
        	{
        		rt=(rt==0)?build_rt():rt;
        		tree[rt].sum+=val;
        		if(l==r)
        		{
        			return;
        		}
        		int mid=(l+r)/2;
        		if(pos<=mid)
        		{
        			update2(lson(rt),l,mid,pos,val);
        		}
        		else
        		{
        			update2(rson(rt),mid+1,r,pos,val);
        		}
        	}
        	int query(int rt1[],int len1,int rt2[],int len2,int l,int r,int k)
        	{
        		if(l==r)
        		{
        			return l;
        		}
        		int mid=(l+r)/2,sum=0;
        		for(int i=1;i<=len2;i++)
        		{
        			sum+=tree[lson(rt2[i])].sum;
        		}
        		for(int i=1;i<=len1;i++)
        		{
        			sum-=tree[lson(rt1[i])].sum;
        		}
        		if(k<=sum)
        		{
        			for(int i=1;i<=len2;i++)
        			{
        				rt2[i]=lson(rt2[i]);
        			}
        			for(int i=1;i<=len1;i++)
        			{
        				rt1[i]=lson(rt1[i]);
        			}   
        			return query(rt1,len1,rt2,len2,l,mid,k);
        		}
        		else
        		{
        			for(int i=1;i<=len2;i++)
        			{
        				rt2[i]=rson(rt2[i]);
        			}
        			for(int i=1;i<=len1;i++)
        			{
        				rt1[i]=rson(rt1[i]);
        			}   
        			return query(rt1,len1,rt2,len2,mid+1,r,k-sum);
        		}
        	}
        }T;
        struct BIT
        {
        	int rt[2][32];
        	int lowbit(int x)
        	{
        		return (x&(-x));
        	}
        	void add(int n,int x,int val)
        	{
        		int pos=lower_bound(b+1,b+1+b[0],a[x])-b;
        		for(int i=x;i<=n;i+=lowbit(i))
        		{
        			T.update2(T.root2[i],1,b[0],pos,val);
        		}
        	}
        	int query(int l,int r,int k)
        	{
        		memset(rt,0,sizeof(rt));
        		for(int i=r;i>=1;i-=lowbit(i))
        		{
        			rt[1][0]++;
        			rt[1][rt[1][0]]=T.root2[i];
        		}
        		rt[1][0]++;
        		rt[1][rt[1][0]]=T.root1[r];
        		for(int i=l-1;i>=1;i-=lowbit(i))
        		{
        			rt[0][0]++;
        			rt[0][rt[0][0]]=T.root2[i];
        		}
        		rt[0][0]++;
        		rt[0][rt[0][0]]=T.root1[l-1];
        		return T.query(rt[0],rt[0][0],rt[1],rt[1][0],1,b[0],k);
        	}
        }B;
        int main()
        {
        	int n,m,i;
        	cin>>n>>m;
        	for(i=1;i<=n;i++)
        	{
        		cin>>a[i];
        		b[0]++;
        		b[b[0]]=a[i];
        	}
        	for(i=1;i<=m;i++)
        	{
        		cin>>q[i].pd>>q[i].l>>q[i].r;
        		if(q[i].pd=='Q')
        		{
        			cin>>q[i].k;
        		}
        		else
        		{
        			b[0]++;
        			b[b[0]]=q[i].r;
        		}
        	}
        	sort(b+1,b+1+b[0]);
        	b[0]=unique(b+1,b+1+b[0])-(b+1);
        	T.build_tree(T.root1[0],1,b[0]);
        	for(i=1;i<=n;i++)
        	{
        		T.update1(T.root1[i-1],T.root1[i],1,b[0],lower_bound(b+1,b+1+b[0],a[i])-b);
        	}
        	for(i=1;i<=m;i++)
        	{
        		if(q[i].pd=='Q')
        		{
        			cout<<b[B.query(q[i].l,q[i].r,q[i].k)]<<endl;
        		}
        		else
        		{
        			B.add(n,q[i].l,-1);
        			a[q[i].l]=q[i].r;
        			B.add(n,q[i].l,1);
        		}
        	}    
        	return 0;
        }
        
  • 离散化来减小常数。

luogu [CQOI2015] 任务查询系统

luogu P3302 [SDOI2013] 森林

luogu P3722 [AH2017/HNOI2017] 影魔

BZOJ4026 dC Loves Number Theory

luogu P4587 [FJOI2016] 神秘数

posted @ 2024-07-22 06:34  hzoi_Shadow  阅读(16)  评论(0编辑  收藏  举报
扩大
缩小
/*
*/