AtCoder Beginner Contest 363

ABC363 A - Piling Up

题目传送门


代码(签到题)

#include <iostream>
using namespace std;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int n;
	cin>>n;
	cout<<100-(n%100);
	return 0;
}

ABC363 B - Japanese Cursed Doll

题目传送门


代码(签到题)

#include <iostream>
#include <algorithm>
using namespace std;
int n,t,p,a[111];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>t>>p;
	for (int i=1;i<=n;++i) cin>>a[i];
	sort(a+1,a+1+n);
	cout<<max(t-a[n-p+1],0);
	return 0;
}

ABC363 C - Avoid K Palindrome 2

题目传送门


分析

统计字母出现次数搜索方案数即可


代码

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string str,Str;
int c[26],n,k,ans;
void dfs(int dep){
	if (dep==n){
		for (int i=0;i<=n-k;++i){
			int cnt=0;
			for (int j=0;j<k/2;++j)
			if (Str[i+j]==Str[i+k-1-j])
			    ++cnt;
			if (cnt==k/2) return;
		}
		++ans;
		return;
	}
	for (int i=0;i<26;++i)
	if (c[i]){
		--c[i];
		Str[dep]=(char)97+i;
		dfs(dep+1);
		++c[i];
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>k>>str,Str=str;
	for (int i=0;i<n;++i) ++c[str[i]-97];
	dfs(0);
	cout<<ans;
	return 0;
}

ABC363 D - Palindromic Number

题目传送门


分析

枚举位数后由于回文的性质可通过前半部分推导后半部分,所以按照位数构造即可


代码

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
typedef long long lll;
lll n,d[33];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	if (n==1){
		cout<<0;
		return 0;
	}else --n;
	for (lll now=1;;now*=10){
		if (n>now*9) n-=now*9;
		else{
			n+=now-1;
			while (n)
				d[++d[0]]=n%10,n/=10;
		    for (int i=d[0];i>1;--i) cout<<d[i];
			for (int i=1;i<=d[0];++i) cout<<d[i];
			break;
		}
		if (n>now*9) n-=now*9;
		else{
			n+=now-1;
			while (n)
				d[++d[0]]=n%10,n/=10;
			for (int i=d[0];i>=1;--i) cout<<d[i];
			for (int i=1;i<=d[0];++i) cout<<d[i];
			break;
		}
	}
	return 0;
}

ABC363 E - Sinking Land

题目传送门


分析

把边界的点加入小根堆然后用水深限制搜索的范围


代码

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
const int N=1011,dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
struct rec{
	int x,y,z;
	bool operator <(const rec &t)const{
		return z>t.z;
	}
};
priority_queue<rec>q;
int n,m,k,a[N][N],v[N][N];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m>>k;
	for (int i=1;i<=n;++i)
	for (int j=1;j<=m;++j){
		cin>>a[i][j];
		if (i==1||i==n||j==1||j==m){
			q.push((rec){i,j,a[i][j]});
			v[i][j]=1;
		}
	}
	for (int i=1,now=n*m;i<=k;++i){
		while (!q.empty()&&q.top().z<=i){
			rec t=q.top(); q.pop(); --now;
			for (int j=0;j<4;++j){
				int x=t.x+dx[j],y=t.y+dy[j];
				if (x<1||x>n||y<1||y>m) continue;
				if (!v[x][y]){
					v[x][y]=1;
					q.push((rec){x,y,a[x][y]});
				}
			}
		}
		cout<<now<<'\n';
	}
	return 0;
}

ABC363 F - Palindromic Expression

题目传送门


分析

如果 \(n\) 本身就是数位不含 \(0\) 的回文数直接输出即可,否则就默认了算式一定含有乘号

不妨强行让算式中的数字个数为奇数个(否则可以在最中间插入 \(1\)

算式中的数必须都是 \(n\) 的约数且数位不含 \(0\),最中间的数要求回文,两边的数要求翻转后也是约数,那么搜索翻转的数与原数乘积,一直除除到剩下回文数停止。


代码

#include <iostream>
#include <queue>
#include <map>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=1000011;
typedef long long lll;
map<lll,lll>uk,hw;
lll d[N],b[N],bl,B[N],n,m,tot,flag;
bool palindrome(lll n){
	d[0]=0;
	while (n){
		d[++d[0]]=n%10;
		n/=10;
	}
	for (int i=1;i<=d[0]/2;++i)
	if (d[i]!=d[d[0]-i+1]) return 0;
	return 1;
}
bool withoutzero(lll n){
	while (n)
	if (n%10==0) return 0;
	    else n/=10;
	return 1;
}
void dfs(lll n){
	if (flag) return;
	if (hw[n]){
		for (int i=1;i<=tot;++i) cout<<uk[B[i]]<<'*';
		cout<<n,flag=1;
		for (int i=tot;i;--i) cout<<'*'<<B[i]/uk[B[i]];
		return;
	}
	for (int i=1;i<=m;++i){
		if (b[i]>n||flag) break;
		if (n%b[i]==0){
			B[++tot]=b[i];
			dfs(n/b[i]);
			--tot;
		}
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n,bl=sqrt(n);
	if (palindrome(n)&&withoutzero(n)){
		cout<<n;
		return 0;
	}
	hw[1]=1;
	for (lll i=2;i<=bl;++i)
	if (n%i==0){
		if (withoutzero(i)){
			if (palindrome(i)) hw[i]=1;
			d[0]=0;
			lll j=i;
			while (j) d[++d[0]]=j%10,j/=10;
			for (int o=1;o<=d[0];++o) j=j*10+d[o];
			if ((n/i)%j==0&&!uk[i*j]){
				b[++m]=i*j,uk[i*j]=i;
			}
		}
		if (withoutzero(n/i)&&palindrome(n/i)) hw[n/i]=1;
	}
	sort(b+1,b+1+m);
	dfs(n);
	if (!flag) cout<<-1;
	return 0;
}

ABC363 G - Dynamic Scheduling

题目传送门


分析

实际上这题跟 [CTSC2015] 日程管理 几乎一模一样
要考虑的是添加和删除两种情况,考虑维护两个集合,一个是已选集合,一个是备选集合。
添加的时候要判断它能不能放进去,实际上就是截止日期不超过它的位置至少有一个位置没放。
用一棵线段树维护最小值,添加或删除时将截止日期到末尾的一段后缀加减一并维护最小值连续区间的左右端点。
如果放不进去,就从 \(0\) 的位置最左侧前找到最小值尝试替换,需要开线段树并在叶节点维护 multiset
删除的时候如果本来就在备选集合直接删除,否则删除后在备选集合挑最大的出来,仍然是用 multiset 维护,所以一共是三棵线段树


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
const int N=100011;
int n,Q,lazy[N<<2],a[N],b[N]; long long ans;
struct rec{int mn,l,r;}w[N<<2];
int iut(){
	int ans=0,f=1; char c=getchar();
	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans*f;
}
struct Segment_Tree{
	pii w[2][N<<2]; multiset<int>K[2][N];
	void build(int k,int l,int r){
		if (l==r){
			w[0][k]=make_pair(0x7f7f7f7f,l);
			w[1][k]=make_pair(0x80808080,l);
			return;
		}
		int mid=(l+r)>>1;
		build(k<<1,l,mid);
		build(k<<1|1,mid+1,r);
		w[0][k]=make_pair(0x7f7f7f7f,l);
		w[1][k]=make_pair(0x80808080,r);
	}
	void update(int opt,int k,int l,int r,int x,int y,int z){
		if (l==r){
			if (z==1){
				K[opt][l].insert(y);
				w[opt][k]=make_pair(opt?(*K[opt][l].rbegin()):(*K[opt][l].begin()),x);
			}else{
				K[opt][l].erase(K[opt][l].find(y));
				if (K[opt][l].empty()) w[opt][k]=make_pair(opt?0x80808080:0x7f7f7f7f,x);
				    else w[opt][k]=make_pair(opt?(*K[opt][l].rbegin()):(*K[opt][l].begin()),x);
			}
			return;
		}
		int mid=(l+r)>>1;
		if (x<=mid) update(opt,k<<1,l,mid,x,y,z);
		    else update(opt,k<<1|1,mid+1,r,x,y,z);
		if (opt) w[opt][k]=w[opt][k<<1].first<w[opt][k<<1|1].first?w[opt][k<<1|1]:w[opt][k<<1];
		    else w[opt][k]=w[opt][k<<1].first>w[opt][k<<1|1].first?w[opt][k<<1|1]:w[opt][k<<1];
	}
	pii query(int opt,int k,int l,int r,int x,int y){
		if (l==x&&r==y) return w[opt][k];
		int mid=(l+r)>>1;
		if (y<=mid) return query(opt,k<<1,l,mid,x,y);
		else if (x>mid) return query(opt,k<<1|1,mid+1,r,x,y);
		else{
			pii _t0=query(opt,k<<1,l,mid,x,mid);
			pii _t1=query(opt,k<<1|1,mid+1,r,mid+1,y);
			if (opt) return _t0.first<_t1.first?_t1:_t0;
			    else return _t0.first>_t1.first?_t1:_t0;
		}
	}
}T;
void build(int k,int l,int r){
	if (l==r){
		w[k]=(rec){l,l,l};
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	w[k]=(rec){l,l,l};
}
void update(int k,int l,int r,int x,int y,int z){
	if (l==x&&r==y){
		w[k].mn+=z,lazy[k]+=z;
		return;
	}
	int mid=(l+r)>>1;
	if (lazy[k]){
		w[k<<1].mn+=lazy[k],w[k<<1|1].mn+=lazy[k];
		lazy[k<<1]+=lazy[k],lazy[k<<1|1]+=lazy[k],lazy[k]=0;
	}
	if (y<=mid) update(k<<1,l,mid,x,y,z);
	else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
	    else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
	if (w[k<<1].mn==w[k<<1|1].mn) w[k]=(rec){w[k<<1].mn,w[k<<1].l,w[k<<1|1].r};
	    else w[k]=w[k<<1].mn<w[k<<1|1].mn?w[k<<1]:w[k<<1|1];
}
rec query(int k,int l,int r,int x,int y){
	if (l==x&&r==y) return w[k];
	int mid=(l+r)>>1;
	if (lazy[k]){
		w[k<<1].mn+=lazy[k],w[k<<1|1].mn+=lazy[k];
		lazy[k<<1]+=lazy[k],lazy[k<<1|1]+=lazy[k],lazy[k]=0;
	}
	if (y<=mid) return query(k<<1,l,mid,x,y);
	else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
	else{
		rec t0=query(k<<1,l,mid,x,mid),t1=query(k<<1|1,mid+1,r,mid+1,y);
		if (t0.mn==t1.mn) return (rec){t0.mn,t0.l,t1.r};
		    else return t0.mn<t1.mn?t0:t1;
	}
}
void Add(int x,int y){
	rec t=query(1,1,n,x,n);
	if (t.mn>0){
		update(1,1,n,x,n,-1);
		T.update(0,1,1,n,x,y,1),ans+=y;
	}else{
		pii _t=T.query(0,1,1,n,1,t.l);
		if (_t.first>=y) T.update(1,1,1,n,x,y,1);
		else{
			ans+=y-_t.first;
			T.update(0,1,1,n,_t.second,_t.first,-1);
			T.update(1,1,1,n,_t.second,_t.first,1);
			T.update(0,1,1,n,x,y,1);
			if (_t.second<x) update(1,1,n,_t.second,x-1,1);
			    else if (_t.second>x) update(1,1,n,x,_t.second-1,-1);
		}
	}
}
void Del(int x,int y){
	if (T.K[0][x].find(y)==T.K[0][x].end()) T.update(1,1,1,n,x,y,-1);
	else{
		ans-=y; pii _t=make_pair(0x80808080,0);
		T.update(0,1,1,n,x,y,-1);
		update(1,1,n,x,n,1);
		if (w[1].mn>0) _t=T.w[1][1];
		    else if (w[1].r<n) _t=T.query(1,1,1,n,w[1].r+1,n);
		if (_t.first!=0x80808080){
			T.update(1,1,1,n,_t.second,_t.first,-1);
			T.update(0,1,1,n,_t.second,_t.first,1);
			update(1,1,n,_t.second,n,-1);
			ans+=_t.first;
		}
	}
}
int main(){
	n=iut(),Q=iut();
	build(1,1,n),T.build(1,1,n);
    for (int i=1;i<=n;++i) a[i]=iut();
    for (int i=1;i<=n;++i) b[i]=iut();
    for (int i=1;i<=n;++i) Add(a[i],b[i]);
	for (int i=1;i<=Q;++i){
        int t=iut(),x=iut(),y=iut();
        Del(a[t],b[t]),Add(a[t]=x,b[t]=y);
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2024-10-07 14:35  lemondinosaur  阅读(8)  评论(0编辑  收藏  举报