【比賽記錄】ARC133

復健訓練了屬於是))

A

考慮直接找第一個不上升的位置。如果沒有就直接選最後一個數。

#include <bits/stdc++.h>
using namespace std;
typedef double db;
#define int long long
#define fi first
#define se second
#define mk make_pair
#define pb emplace_back
#define poly vector<int>
#define Bt(a) bitset<a>
#define bc __builtin_popcount
#define pc putchar
#define ci const int&
const int mod = 1e9 + 7;
const db eps = 1e-10;
const int inf = (1 << 30);
inline int Max(ci x, ci y) {return x > y ? x : y;}
inline int Min(ci x, ci y) {return x < y ? x : y;}
inline db Max(db x, db y) {return x - y > eps ? x : y;}
inline db Min(db x, db y) {return x - y < eps ? x : y;}
inline int Add(ci x, ci y, ci M = mod) {return (x + y) % M;}
inline int Mul(ci x, ci y, ci M = mod) {return 1ll * x * y % M;}
inline int Dec(ci x, ci y, ci M = mod) {return (x - y + M) % M;}
typedef pair<int, int> pii;
inline int Abs(int x) {return x < 0 ? -x : x;}
//char buf[1<<21],*p1=buf,*p2=buf;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char Obuf[105000],*O=Obuf;//Siz shoule be the size of Out File
int pst[30],ptop;
inline void Fprint(){fwrite(Obuf,1,O-Obuf,stdout);}
inline void Fwrite(int x){
  if(x==0){*O++='0';return;}
  if(x<0)*O++='-',x=-x;ptop=0;
  while(x)pst[++ptop]=x%10,x/=10;
  while(ptop)*O++=pst[ptop--]+'0';
  if(O-Obuf>100000)Fprint(),O=Obuf;
}
inline int read() {
    int s = 0, w = 1;
    char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') w = -1;ch = getchar();}
    while (isdigit(ch)) {s = s * 10 + ch - '0';ch = getchar();}
    return s * w;
}
inline void write(int x) {
    if (x < 0)putchar('-'), x = -x;
    if (x > 9)write(x / 10);
	pc(x % 10 + '0');
}
inline int qpow(int x, int y) {
    int res = 1;
    while (y) {if (y & 1)res = Mul(res, x);x = Mul(x, x);y >>= 1;}
    return res;
}
inline void cadd(int &x, int y) {x += y;}
inline void cmul(int &x, int y) {x *= y;}
inline void cmax(int &x, int y) {x = Max(x, y);}
inline void cmin(int &x, int y) {x = Min(x, y);}
const int N = 2e5 + 10;
namespace Refined_heart{
	int n,a[N]; 
	void solve(){
		n=read();
		for(int i=1;i<=n;++i)a[i]=read();
		int pre=-1;
		for(int i=1;i<=n;++i){
			if(pre>a[i]){
				break;
			}
			cmax(pre,a[i]);
		}
		if(pre==-1)pre=a[n];
		poly A;
		for(int i=1;i<=n;++i)if(a[i]!=pre)A.pb(a[i]);
		for(auto v:A)write(v),pc(' ');
	}
}
signed main(){
	Refined_heart::solve();
	return 0;
}

B

仔細讀題,這是排列。

考慮暴力找到每個 \(A_i\) 的倍數,然後直接設 \(f_{i,j}\) 表示 \(A_i\) 從位置 \(j\) 轉移過來的方案數。

這是因爲,我們的總有效狀態只有 \(\sum \frac{n}{i}=n\ln n\) 個。

然後考慮轉移。設我們要匹配的位置是 \(now,\) 那麼之前所有值的匹配位置都不能超過 \(now.\)

所以找一個數據結構來維護前綴最大值以及單點修改即可。這裏寫了一個線段樹。

#include <bits/stdc++.h>
using namespace std;
typedef double db;
#define int long long
#define fi first
#define se second
#define mk make_pair
#define pb emplace_back
#define poly vector<int>
#define Bt(a) bitset<a>
#define bc __builtin_popcount
#define pc putchar
#define ci const int&
const int mod = 1e9 + 7;
const db eps = 1e-10;
const int inf = (1 << 30);
inline int Max(ci x, ci y) {return x > y ? x : y;}
inline int Min(ci x, ci y) {return x < y ? x : y;}
inline db Max(db x, db y) {return x - y > eps ? x : y;}
inline db Min(db x, db y) {return x - y < eps ? x : y;}
inline int Add(ci x, ci y, ci M = mod) {return (x + y) % M;}
inline int Mul(ci x, ci y, ci M = mod) {return 1ll * x * y % M;}
inline int Dec(ci x, ci y, ci M = mod) {return (x - y + M) % M;}
typedef pair<int, int> pii;
inline int Abs(int x) {return x < 0 ? -x : x;}
//char buf[1<<21],*p1=buf,*p2=buf;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char Obuf[105000],*O=Obuf;//Siz shoule be the size of Out File
int pst[30],ptop;
inline void Fprint(){fwrite(Obuf,1,O-Obuf,stdout);}
inline void Fwrite(int x){
  if(x==0){*O++='0';return;}
  if(x<0)*O++='-',x=-x;ptop=0;
  while(x)pst[++ptop]=x%10,x/=10;
  while(ptop)*O++=pst[ptop--]+'0';
  if(O-Obuf>100000)Fprint(),O=Obuf;
}
inline int read() {
    int s = 0, w = 1;
    char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') w = -1;ch = getchar();}
    while (isdigit(ch)) {s = s * 10 + ch - '0';ch = getchar();}
    return s * w;
}
inline void write(int x) {
    if (x < 0)putchar('-'), x = -x;
    if (x > 9)write(x / 10);
	pc(x % 10 + '0');
}
inline int qpow(int x, int y) {
    int res = 1;
    while (y) {if (y & 1)res = Mul(res, x);x = Mul(x, x);y >>= 1;}
    return res;
}
inline void cadd(int &x, int y) {x += y;}
inline void cmul(int &x, int y) {x *= y;}
inline void cmax(int &x, int y) {x = Max(x, y);}
inline void cmin(int &x, int y) {x = Min(x, y);}
const int N = 2e6 + 10;
namespace Refined_heart{
	int n,a[N],b[N];
	int pos[N];
	unordered_map<int,int>f[N];
	namespace SGT{
		int maxn[N];
		void build(int l,int r,int x){
			if(l==r)return;
			int mid=(l+r)>>1;
			build(l,mid,x<<1);
			build(mid+1,r,x<<1|1);
		}
		inline void pushup(int x){
			cmax(maxn[x],Max(maxn[x<<1],maxn[x<<1|1]));
		}
		void change(int x,int l,int r,int pos,int v){
			if(l==r){
				cmax(maxn[x],v);
				return;
			}
			int mid=(l+r)>>1;
			if(pos<=mid)change(x<<1,l,mid,pos,v);
			else change(x<<1|1,mid+1,r,pos,v);
			pushup(x);
		}
		int query(int x,int L,int R,int l,int r){
			if(L>=l&&R<=r)return maxn[x];
			int ans=-1,mid=(L+R)>>1;
			if(l<=mid)ans=Max(ans,query(x<<1,L,mid,l,r));
			if(mid<r)ans=Max(ans,query(x<<1|1,mid+1,R,l,r));
			return ans;
		}
	}
	using namespace SGT;
	vector<pii>nxt;
	void solve(){
		n=read();build(1,n,1); 
		for(int i=1;i<=n;++i)a[i]=read();
		for(int i=1;i<=n;++i)b[i]=read();
		for(int i=1;i<=n;++i)pos[b[i]]=i;
		for(int i=a[1];i<=n;i+=a[1]){
			f[1][pos[i]]=1;
			change(1,1,n,pos[i],1);
		}
		for(int i=2;i<=n;++i){
			for(int j=a[i];j<=n;j+=a[i]){
				int now=pos[j];
				if(now==1)f[i][now]=1;
				else f[i][now]=query(1,1,n,1,now-1)+1;
				nxt.pb(mk(now,f[i][now]));
			}
			for(auto v:nxt){
				int ps=v.fi;
				int vl=v.se;
				change(1,1,n,ps,vl);
			}
			nxt.clear();
		}
		int ans=-1;
		for(int i=1;i<=n;++i){
			for(int j=a[i];j<=n;j+=a[i]){
				cmax(ans,f[i][pos[j]]);
			}
		}
		write(ans);
	}
}
signed main(){
	Refined_heart::solve();
	return 0;
}

C

貪心神題。

首先考慮將所有位置填成 \(k-1,\) 再進行調整。

那麼對於 \(a_i,\) 這一行要修改的數自然就是 \(m\times (k-1)-a_i.\) 這是最少的修改次數。

設所有行的修改數的和爲 \(C_i,\) 列的爲 \(D_i,\) 那麼我們考慮證明答案是 \(n\times m\times (k-1)-\max\{\sum c,\sum d\}\)

首先,無解當且僅當 \(\sum a\not\equiv \sum b\) 這是因爲兩側都是所有數的和。

那麼,考慮給 \(c,d\) 中較小的加上一個 \(k\) 的倍數使得二者相等。

那麼考慮重複下列操作直到矩陣爲 \(0\)

  • 找到一個位置滿足 \(c_i>0,d_i>0\) 並令二者減一

在上述的調整上,沒有一個數會被修改爲負數。而修改次數就恰好是 \(\max\{\sum c,\sum d\}\)

#include <bits/stdc++.h>
using namespace std;
typedef double db;
#define int long long
#define fi first
#define se second
#define mk make_pair
#define pb emplace_back
#define poly vector<int>
#define Bt(a) bitset<a>
#define bc __builtin_popcount
#define pc putchar
#define ci const int&
const int mod = 1e9 + 7;
const db eps = 1e-10;
const int inf = (1 << 30);
inline int Max(ci x, ci y) {return x > y ? x : y;}
inline int Min(ci x, ci y) {return x < y ? x : y;}
inline db Max(db x, db y) {return x - y > eps ? x : y;}
inline db Min(db x, db y) {return x - y < eps ? x : y;}
inline int Add(ci x, ci y, ci M = mod) {return (x + y) % M;}
inline int Mul(ci x, ci y, ci M = mod) {return 1ll * x * y % M;}
inline int Dec(ci x, ci y, ci M = mod) {return (x - y + M) % M;}
typedef pair<int, int> pii;
inline int Abs(int x) {return x < 0 ? -x : x;}
//char buf[1<<21],*p1=buf,*p2=buf;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char Obuf[105000],*O=Obuf;//Siz shoule be the size of Out File
int pst[30],ptop;
inline void Fprint(){fwrite(Obuf,1,O-Obuf,stdout);}
inline void Fwrite(int x){
  if(x==0){*O++='0';return;}
  if(x<0)*O++='-',x=-x;ptop=0;
  while(x)pst[++ptop]=x%10,x/=10;
  while(ptop)*O++=pst[ptop--]+'0';
  if(O-Obuf>100000)Fprint(),O=Obuf;
}
inline int read() {
    int s = 0, w = 1;
    char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') w = -1;ch = getchar();}
    while (isdigit(ch)) {s = s * 10 + ch - '0';ch = getchar();}
    return s * w;
}
inline void write(int x) {
    if (x < 0)putchar('-'), x = -x;
    if (x > 9)write(x / 10);
	pc(x % 10 + '0');
}
inline int qpow(int x, int y) {
    int res = 1;
    while (y) {if (y & 1)res = Mul(res, x);x = Mul(x, x);y >>= 1;}
    return res;
}
inline void cadd(int &x, int y) {x += y;}
inline void cmul(int &x, int y) {x *= y;}
inline void cmax(int &x, int y) {x = Max(x, y);}
inline void cmin(int &x, int y) {x = Min(x, y);}
const int N = 2e5 + 10;
namespace Refined_heart{
	int n,m,k,a[N],b[N];
	void solve(){
		n=read();m=read();k=read();
		for(int i=1;i<=n;++i)a[i]=read();
		for(int i=1;i<=m;++i)b[i]=read();
		int A=0,B=0;
		for(int i=1;i<=n;++i)A+=(m*(k-1)-a[i])%k;
		for(int i=1;i<=m;++i)B+=(n*(k-1)-b[i])%k;
		if(A%k!=B%k){
			puts("-1");
			return;
		}
		int ans=(k-1)*n*m;
		ans-=Max(A,B);
		cout<<ans<<endl;
	}
}
signed main(){
	Refined_heart::solve();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章