ICPC2024杭州站

A. AUS

#include <bits/stdc++.h>
using namespace std;
int fa[30];
int get(int x)
{
	if(fa[x]==x)
	{
		return x;
	}
	return fa[x]=get(fa[x]);
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		string s1,s2,s3;
		cin>>s1>>s2>>s3;
		if(s1.size()!=s2.size())
		{
			cout<<"NO"<<endl;
			continue;
		}
		if(s1.size()!=s3.size())
		{
			cout<<"YES"<<endl;
			continue;
		}
		for(int i=0;i<26;i++)
		{
			fa[i]=i;
		}
		for(int i=0;i<s1.size();i++)
		{
			if(s1[i]!=s2[i])
			{
				fa[get(s1[i]-'a')]=get(s2[i]-'a');
			}
		}
		bool f=false;
		for(int i=0;i<s1.size();i++)
		{
			if(get(s1[i]-'a')!=get(s3[i]-'a'))
			{
				f=true;
				break;
			}
		}
		f==true? cout<<"YES\n":cout<<"NO\n";
	}
	return 0;
}

K. Kind of Bingo

  • 注意答案有>=m的下限
#include <bits/stdc++.h>
using namespace std;
vector<int>a[100005];
int p[100005],h[100005];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		int n,m,k;
		cin>>n>>m>>k;
		for(int i=1;i<=n;i++)
		{
			a[i].clear();
		}
		for(int i=1;i<=n*m;i++)
		{
			cin>>p[i];
			h[p[i]]=i;
			a[p[i]/m+(p[i]%m>0)].push_back(p[i]);
		}
		if(k>=m)
		{
			cout<<m<<"\n";
			continue;
		}
		else
		{
			int ans=n*m;
			k=m-k;
			for(int i=1;i<=n;i++)
			{
				ans=min(ans,h[a[i][k-1]]);
			}
			cout<<max(ans,m)<<"\n";
		}
	}
	return 0;
}

E. Elevator II

  • 先以尽量少的代价到达顶层,之后排一下序就好了
#include <bits/stdc++.h>
using namespace std;
struct t1
{
	int l,r,id;
}t[100005];
vector<int>ans;
bool cmpl(t1 a,t1 b)
{
	return a.l<b.l;
}
bool cmpr(t1 a,t1 b)
{
	return a.r<b.r;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		int n,f;
		cin>>n>>f;
		for(int i=1;i<=n;i++)
		{
			cin>>t[i].l>>t[i].r;
			t[i].id=i;
		}
		sort(t+1,t+n+1,cmpl);
		int p=0,cur=f;
		long long sum=0;
		ans.clear();
		while(p<n)
		{
			while(p<n&&t[p+1].l<=cur)
			{
				p++;
				sum=sum+t[p].r-t[p].l;
				if(t[p].r>cur)
				{
					ans.push_back(t[p].id);
					t[p].id=0;
					cur=t[p].r;
				}
			}
			if(p<n)
			{
				p++;
				sum=sum+t[p].r-cur;
				cur=t[p].r;
				ans.push_back(t[p].id);
				t[p].id=0;
			}
		}
		sort(t+1,t+n+1,cmpr);
		for(int i=n;i>=1;i--)
		{
			if(t[i].id)
			{
				ans.push_back(t[i].id);
			}
		}
		cout<<sum<<"\n";
		for(auto x:ans)
		{
			cout<<x<<" ";
		}
		cout<<"\n";
	}
	return 0;
}

M. Make It Divisible

  • 一开始觉得程序应该过不去,但还是交了一下,没想到直接过了……本以为是数据弱,后来想了一下好像是自己的时间复杂度算错了,不是\(\sqrt{bi} \cdot n\),是约数个数*n呀!
#include <bits/stdc++.h>
using namespace std;
int b[50005],c[50005],minn,maxn;
long long cnt,sum;
long long n,K;
bool pd()
{
	stack<int>s;
	for(int i=1;i<=n;i++)
	{
		while(s.size()&&s.top()>=c[i])
		{
			if(s.top()%c[i]==0)
			{
				s.pop();
			}
			else
			{
				return false;
			}
		}
		if(s.empty()||c[i]%s.top()==0)
		{
			s.push(c[i]);
		}
		else
		{
			return false;
		}
	}
	return true;
}
void calc(long long k)
{
	long long x=(maxn-k*minn)/(k-1);
	if(x>=1&&x<=K)
	{
		for(int i=1;i<=n;i++)
		{
			c[i]=b[i]+x;
		}
		if(pd())
		{
			cnt++;
			sum+=x;
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>K;
		for(int i=1;i<=n;i++)
		{
			cin>>b[i];
		}
		minn=*min_element(b+1,b+n+1);
		maxn=*max_element(b+1,b+n+1);
		for(int i=1;i<=n;i++)
		{
			if(b[i]>minn&&b[i]<maxn)
			{
				maxn=b[i];
			}
		}
		int m=maxn-minn;
		if(m==0)
		{
			cout<<K<<" "<<K*(K+1)/2<<"\n";
			continue;
		}
		cnt=0,sum=0;
		for(long long i=1;i*i<=m;i++)
		{
			if(m%i==0)
			{
				calc(i+1);
				if(i*i!=m)
				{
					calc(m/i+1);
				}
			}
		}
		cout<<cnt<<" "<<sum<<"\n";
	}
	return 0;
}

H. Heavy-light Decomposition

  • 第一遍没构造对也没关系,多做几遍,总会得到正确答案的呀~
  • 考虑以最长的一条重链为基础构造,观察到所有长度和它不同的链都可以接在根节点上。如果其他链的长度都比它小,直接这么做就好了;否则,考察是否存在一条长度至少比它短2的链,如果存在,就把它拿出来接在根节点的子节点上,否则无解
#include <bits/stdc++.h>
using namespace std;
struct t1
{
	int l,r,len;
}t[100005];
int p[100005];
bool cmp(t1 a,t1 b)
{
	return a.len>b.len;
}
int n,k;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>k;
		for(int i=1;i<=k;i++)
		{
			cin>>t[i].l>>t[i].r;
			t[i].len=t[i].r-t[i].l+1;
			for(int j=t[i].l;j<t[i].r;j++)
			{
				p[j+1]=j;
			}
		}
		if(n==1)
		{
			cout<<"0\n";
			continue;
		}
		sort(t+1,t+k+1,cmp);
		p[t[1].l]=0;
		if(k==1)
		{
			for(int i=1;i<n;i++)
			{
				cout<<p[i]<<" ";
			}
			cout<<p[n]<<"\n";
			continue;
		}
		if(t[1].len==t[2].len&&t[k].len>=t[1].len-1)
		{
			cout<<"IMPOSSIBLE"<<"\n";
			continue;
		}
		for(int i=2;i<k;i++)
		{
			p[t[i].l]=t[1].l;
		}
		if(t[1].len==t[2].len)
		{
			p[t[k].l]=t[1].l+1;
		}
		else
		{
			p[t[k].l]=t[1].l;
		}
		for(int i=1;i<n;i++)
		{
			cout<<p[i]<<" ";
		}
		cout<<p[n]<<"\n";
	}
	return 0;
}

F. Fuzzy Ranking

  • 眨了一下眼,看见了询问的性质:序列在原图上对应一条链,问题就解决啦!
#include <bits/stdc++.h>
using namespace std;
vector<long long>p[200005],sum[200005];
typedef pair<int,int> pii;
vector<pii>op[200005];
vector<int>a[500005];
int dfn[500005],low[500005],tot,cnt,id[500005];
bool ins[500005];
stack<int>s;
void tarjan(int n1)
{
	dfn[n1]=low[n1]=++tot;
	s.push(n1);
	ins[n1]=true;
	for(int i=0;i<a[n1].size();i++)
	{
		if(!dfn[a[n1][i]])
		{
			tarjan(a[n1][i]);
			low[n1]=min(low[n1],low[a[n1][i]]);
		}
		else if(ins[a[n1][i]]==true)
		{
			low[n1]=min(low[n1],dfn[a[n1][i]]);
		}
	}
	if(dfn[n1]==low[n1])
	{
		cnt++;
		while(s.top()!=n1)
		{
			id[s.top()]=cnt;
			ins[s.top()]=false;
			s.pop();
		}
		id[n1]=cnt;
		ins[n1]=false;
		s.pop();
	}
}
long long f(long long x)
{
	return x*(x-1)/2;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		int n,k,q;
		cin>>n>>k>>q;
		for(int i=1;i<=n;i++)
		{
			a[i].clear();
		}
		for(int i=1;i<=k;i++)
		{
			op[i].clear();
			sum[i].clear();
			p[i].clear();
		}
		for(int i=1;i<=k;i++)
		{
			for(int j=1;j<=n;j++)
			{
				int x;
				cin>>x;
				if(p[i].size())
				{
					a[p[i].back()].push_back(x);
				}
				p[i].push_back(x);
			}
		}
		tot=0;
		for(int i=1;i<=n;i++)
		{
			dfn[i]=0;
		}
		for(int i=1;i<=n;i++)
		{
			if(!dfn[i])
			{
				tarjan(i);
			}
		}
		long long l;
		for(int i=1;i<=k;i++)
		{
			l=0;
			for(int j=1;j<n;j++)
			{
				if(id[p[i][j]]!=id[p[i][j-1]])
				{
					op[i].push_back(pii(l,j-1));
					if(sum[i].size())
					{
						sum[i].push_back(f(j-l)+sum[i].back());
					}
					else
					{
						sum[i].push_back(f(j-l));
					}
					l=j;
				}
			}
			op[i].push_back(pii(l,n-1));
			if(sum[i].size())
			{
				sum[i].push_back(f(n-l)+sum[i].back());
			}
			else
			{
				sum[i].push_back(f(n-l));
			}
		}
		long long ans=0;
		for(int i=1;i<=q;i++)
		{
			int id,l,r;
			cin>>id>>l>>r;
			id=(id+ans)%k+1;
			l=(l+ans)%n;
			r=(r+ans)%n;
			auto check1=[l](pii x)
			{
				return x.second<l;
			};
			auto check2=[r](pii x)
			{
				return x.first<=r;
			};
			int p=partition_point(op[id].begin(),op[id].end(),check1)-op[id].begin();
			int q=partition_point(op[id].begin(),op[id].end(),check2)-op[id].begin()-1;
			if(p==q)
			{
				ans=f(r-l+1);
			}
			else
			{
				ans=sum[id][q-1]-sum[id][p]+f(op[id][p].second-l+1)+f(r-op[id][q].first+1);
			}
			cout<<ans<<endl;
		}
	}
	return 0;
}

B. Barkley III

  • 建立63棵线段树维护1的个数,这种做法显而易见,可是连空间都不够开呀!
  • 考虑我们并不关心1的个数,只关心0的个数是否为1,所以我们可以转而维护布尔型变量,可这样时间也不够呀!而且空间还是吃紧
  • 等一下,从int到bool,信息量减少了1/32,可是为什么空间只少了1/4?
  • 原来,由于内存地址是按字节即 byte 寻址,而非比特 bit,一个 bool 类型的变量,虽然只能表示 0/1, 但是也占了 1 byte 的内存———这正是bitset存在的意义呀!
  • 从另一个角度思考,既然每棵线段树之间的操作完全平行,我们完全可以通过状态压缩的方法把它们合并起来呀!
  • __builtin_clzll:consecutive、leading、zero
  • 用64/32减得位的个数,63/31减得最高位的编号
  • 答案错误不要紧,写个朴素程序对拍分分钟的事,错误很快就找出来啦~
  • 进入ask函数前也要判断一下这个区间内是否存在答案;这一步看似是log方,其实依然是log,因为只有一个区间会继续递归
  • 在ask函数内交叉调用另外的ask函数,看似是2log,其实是log方,因为每次调用都要继续递归下去,所以需要把两个ask函数合并起来,以获得单log的时间复杂度
#include <bits/stdc++.h>
using namespace std;
long long a[1000005];
struct t1
{
	int l,r;
	long long state,v,bj;
}t[4000005];
void build(int p,int l,int r)
{
	t[p].l=l;
	t[p].r=r;
	t[p].bj=~0ll;
	if(l==r)
	{
		t[p].state=~a[l];
		t[p].v=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	t[p].state=(t[p*2].state&t[p*2+1].v)|(t[p*2].v&t[p*2+1].state);
	t[p].v=t[p*2].v&t[p*2+1].v;
}
void spread(int p)
{
	if(t[p].bj!=(~0ll))
	{
		t[p*2].bj&=t[p].bj;
		t[p*2+1].bj&=t[p].bj;
		t[p*2].l==t[p*2].r?	t[p*2].state=~(t[p*2].v&t[p].bj):t[p*2].state&=t[p].bj;
		t[p*2+1].l==t[p*2+1].r?	t[p*2+1].state=~(t[p*2+1].v&t[p].bj):t[p*2+1].state&=t[p].bj;
		t[p*2].v&=t[p].bj;
		t[p*2+1].v&=t[p].bj;
		t[p].bj=~0ll;
	}
}
long long ask(int p,int x)
{
	if(t[p].l==t[p].r)
	{
		return t[p].v;
	}
	spread(p);
	if(((t[p*2].v>>x)&1)==0)
	{
		return ask(p*2,x);
	}
	else if(((t[p*2+1].v>>x)&1)==0)
	{
		return ask(p*2+1,x);
	}
	else
	{
		return -1;
	}
}
long long askop(int p,int l,int r,int x)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		if(((t[p].v>>x)&1)==0)
		{
			return ask(p,x);
		}
		return -1;
	}
	spread(p);
	int mid=(t[p].l+t[p].r)>>1;
	long long val=0;
	if(l<=mid)
	{
		val=askop(p*2,l,r,x);
		if(val!=-1)
		{
			return val;
		}
	}
	if(r>mid)
	{
		val=askop(p*2+1,l,r,x);
		if(val!=-1)
		{
			return val;
		}
	}
	return -1;
}
typedef pair<long long,long long> pll;
pll Ask(int p,int l,int r)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		return pll(t[p].v,t[p].state);
	}
	spread(p);
	int mid=(t[p].l+t[p].r)>>1;
	if(l<=mid&&r>mid)
	{
		auto [lval,lst]=Ask(p*2,l,r);
		auto [rval,rst]=Ask(p*2+1,l,r);
		return pll(lval&rval,(lst&rval)|(lval&rst));
	}
	else if(l<=mid)
	{
		return Ask(p*2,l,r);
	}
	else
	{
		return Ask(p*2+1,l,r);
	}
}
void change(int p,int l,int r,long long x)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		t[p].bj&=x;
		t[p].l==t[p].r?	t[p].state=~(t[p].v&x):t[p].state&=x;
		t[p].v&=x;
		return;
	}
	spread(p);
	int mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)
	{
		change(p*2,l,r,x);
	}
	if(r>mid)
	{
		change(p*2+1,l,r,x);
	}
	t[p].state=(t[p*2].state&t[p*2+1].v)|(t[p*2].v&t[p*2+1].state);
	t[p].v=t[p*2].v&t[p*2+1].v;
}
void change(int p,int l,long long x)
{
	if(t[p].l==t[p].r)
	{
		t[p].state=~x;
		t[p].v=x;
		return;
	}
	spread(p);
	int mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)
	{
		change(p*2,l,x);
	}
	else
	{
		change(p*2+1,l,x);
	}
	t[p].state=(t[p*2].state&t[p*2+1].v)|(t[p*2].v&t[p*2+1].state);
	t[p].v=t[p*2].v&t[p*2+1].v;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,q;
	cin>>n>>q;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	build(1,1,n);
	for(int i=1;i<=q;i++)
	{
		int opt,l,r,s;
		long long x;
		cin>>opt;
		if(opt==1)
		{
			cin>>l>>r>>x;
			change(1,l,r,x);
		}
		else if(opt==2)
		{
			cin>>s>>x;
			change(1,s,x);
		}
		else
		{
			cin>>l>>r;
			auto [va,st]=Ask(1,l,r);
			cout<<(va|(st&(~askop(1,l,r,63-__builtin_clzll(st)))))<<"\n";
		}
	}
	return 0;
}
posted @ 2025-03-04 17:14  D06  阅读(182)  评论(0)    收藏  举报
//雪花飘落效果