Loading

noip模拟40

A. 送花

不知道该怎么评价自己想到了线段树优化\(dp\)但觉得第一题不会考\(dp\)所以不再往下考虑的想法.
如果我们找到了和之前相同的值,直接减掉这个权值的贡献就可以了..
大概就是将所有状态都枚举了出来然后用线段树优化直接取最大值.

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll long long int
	#define re register int
	#define ull unsigned ll
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x);
	#define Copy(x,y) memset(y,x,sizeof x);
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=2e6+51;

ll m,n,ans;
ll c[N],d[N];
pair<ll,ll> p[N];
struct I { ll sum,lazy; } tr[N<<2];
inline void spread(ll x){
	if(tr[x].lazy){
		tr[x<<1].sum+=tr[x].lazy,tr[x<<1|1].sum+=tr[x].lazy,
		tr[x<<1].lazy+=tr[x].lazy,tr[x<<1|1].lazy+=tr[x].lazy;
		tr[x].lazy=0;
  	}
}
inline void pushup(ll x){
	tr[x].sum=max(tr[x<<1].sum,tr[x<<1|1].sum);
}
void update(ll x,ll l,ll r,ll ql,ll qr,ll w){
	if(ql>qr or (!qr) ) return ;
	if(l>=ql and r<=qr){
		tr[x].sum+=w,tr[x].lazy+=w;
		return ;
	}
	ll mid=(l+r)>>1; spread(x);
	if(ql<=mid) update(x<<1,l,mid,ql,qr,w);
	if(qr>=mid+1) update(x<<1|1,mid+1,r,ql,qr,w);
	pushup(x);
}
signed main(){
	n=read(); m=read();
	for(re i=1;i<=n;++i) c[i]=read();
	for(re i=1;i<=m;++i) d[i]=read(),p[i].first=0,p[i].second=0;
	ll l,r;
	for(re i=1;i<=n;++i){
		l=p[c[i]].first,r=p[c[i]].second;
		p[c[i]].first=r,p[c[i]].second=i;
		update(1,1,n,l+1,r,-d[c[i]]),update(1,1,n,r+1,i,d[c[i]]);
		ans=max(ans,tr[1].sum);
	//	cout<<"ans:"<<ans<<'\n';
	}
	printf("%lld\n",ans);
	return 0;
}

B. 星空

发现最小距离一定是不为\(0\)的直接距离..
一个我又不会的巧妙转化:
题目中让我们求:
\(|\ |x_1-x_2|\ -\ |y_1-y_2|\ |\)
然后我们四十五度翻转坐标系.
于是\((x,y)\)坐标变为了\((x+y,x-y)\)..
设新的坐标为\((r,c)\).
直接距离就是\(min(\ |r_1-r_2|\ ,\ |c_1-c_2|\ )\).然后我们可以考虑将所有距离为\(0\)的点进行并查集缩点.
然后枚举所有的边,如果这条边的长度即为第一问的答案,那么乘积累加并注意去重即可.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll long long int
	#define re register int
	#define ull unsigned ll
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x);
	#define Copy(x,y) memset(y,x,sizeof x);
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=1e5+51;

ll m,n,dis,ans;
ll fa[N];
struct I { ll x,y,id; } p[N];
inline bool comp1(I i,I j){ return i.x<j.x; }
inline bool comp2(I i,I j){ return i.y<j.y; }
ll find(ll x){ return x==fa[x] ? x : (fa[x]=find(fa[x])) ; }
unordered_map<ll,ll> siz;
map<pair<ll,ll>,ll> map1;
vector<pair<ll,ll> > vec;
signed main(){
	n=read(); ll x,y; dis=1e10,p[0].x=1e10,p[0].y=1e10;
	for(re i=1;i<=n;++i) x=read(),y=read(),p[i].x=x+y,p[i].y=y-x,p[i].id=i;
	sort(p+1,p+1+n,comp1);
	for(re i=1;i<=n;++i){
		if(p[i].x!=p[i-1].x) fa[p[i].id]=p[i].id;
		else fa[p[i].id]=find(p[i-1].id);
	}
	sort(p+1,p+1+n,comp2);
	for(re i=1;i<=n;++i) if(p[i].y==p[i-1].y) fa[find(p[i].id)]=find(fa[p[i-1].id]);
  	for(re i=1;i<=n-1;++i)
  		if(find(p[i].id)!=find(p[i+1].id)){
  			x=abs(p[i].y-p[i+1].y);
  			if(dis>x){
  				vec.clear(); dis=x;
  				x=min(p[i].id,p[i+1].id),y=max(p[i].id,p[i+1].id);
  				vec.push_back(mp(x,y));
  			}
  			else if(dis==x){
  				x=min(p[i].id,p[i+1].id),y=max(p[i].id,p[i+1].id);
  				vec.push_back(mp(x,y));
  			}
  		}
  	sort(p+1,p+1+n,comp1);
  	for(re i=1;i<=n-1;++i)
  		if(find(p[i].id)!=find(p[i+1].id)){
  			x=abs(p[i].x-p[i+1].x);
  			if(dis>x){
  				vec.clear(); dis=x;
  				x=min(p[i].id,p[i+1].id),y=max(p[i].id,p[i+1].id);
  				vec.push_back(mp(x,y));
  			}
  			else if(dis==x){
  				x=min(p[i].id,p[i+1].id),y=max(p[i].id,p[i+1].id);
  				vec.push_back(mp(x,y));
  			}
  		}
	if(vec.empty()) { puts("-1"); return 0; }
	sort(vec.begin(),vec.end());
 	ll newsize=unique(vec.begin(),vec.end())-vec.begin();
 	vec.resize(newsize);
 	for(re i=1;i<=n;++i) ++siz[find(i)];
 	for(auto i : vec){
 		x=find(i.first),y=find(i.second);
		if((!map1[mp(x,y)]) and (!map1[mp(y,x)])) ans+=siz[x]*siz[y];
 		map1[mp(x,y)]=1,map1[mp(y,x)]=1;
 	}
 	printf("%lld\n%lld",dis,ans);
	return 0;
}

C. 零一串

感谢 y_cx 大佬的讲解.
大概就是双端队列维护\(01\)相对位置即可.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll long long int
	#define ull unsigned ll 
	#define re register ll 
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=5e6+21,mod=998244353;

char s[N];
ll n,m,ans,cnt;
ll a[N],c[N],pos[N],cf[N];
deque<ll> que;
inline ll ksm(ll a,ll b,ll c){
	a%=c; ll res=1;
	while(b){
		if(b&1) res=(res*a)%c;
		a=(a*a)%c,b>>=1;
	}
	return res%c;
}
signed main(){
	m=read(),scanf("%s",s+1),n=strlen(s+1); ll tmp,res=0,pre=0;
	for(re i=1;i<=n;i++){
		if(s[i]=='1') a[i]=1,pos[++cnt]=i;
		else a[i]=0,res+=cnt;
	}
	ans=(res%=mod);
	for(int i=1;i<=m;i++) que.push_back(i);
	for(ll i=1;i<=cnt;i++){
		if(que.back()+i>m and que.size()) que.pop_back();
		que.push_front(1-i);
		for(re j=1;j<=pos[i]-pos[i-1]-1 and que.size();j++){
			cf[que.front()+i]++,cf[min(cnt+que.front()+1,m+1)]--;
			que.pop_front();
		}
		c[pos[i]+que.size()-m]=1;
	}
	for(re i=1;i<=m;i++){
		pre=(pre+cf[i])%mod,res=(res+pre)%mod;
		ans=ans xor (ksm(233,i,mod)*res%mod);
	}
	for(re i=1;i<=n;i++) cout<<c[i];
	printf("\n%lld\n",ans),exit(0);
}
posted @ 2021-08-19 19:27  AaMuXiiiiii  阅读(53)  评论(0编辑  收藏  举报