The 2nd Universal Cup. Stage 25: Shenzhen 题解

A A. A Good Problem

A good problem should have a concise statement.
You are given an array a of length n, initially filled with zeros, and another array b of length n. Your goal
is to transform array a into array b. You can perform the following two types of operations:
• 1 x: Add 1 to all elements in a that are equal to x.
• 2 x: Add 1 to the element in a at index x.
You can perform no more than 20 000 operations.

分治,考虑最极端情况为 1 , 2 , ⋯   , n 1,2,\cdots,n 1,2,,n

  1. 先把 [ n / 2 + 1 , n ] [n/2+1,n] [n/2+1,n]区间的数变为 1 1 1
  2. [ n / 2 + 1 , n ] [n/2+1,n] [n/2+1,n]区间的数变为 n / 2 + 1 n/2+1 n/2+1
  3. 处理 [ n / 2 + 1 , n ] [n/2+1,n] [n/2+1,n]区间
  4. 处理 [ 1 , n / 2 ] [1,n/2] [1,n/2]区间
#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
int n,a[1010];
pi pa[1010];
vector<pi > ans;
void work(int l,int r,int now) {
	if(l>r) return;
	while(l<=r && pa[l].fi==now) ++l;
	if(l>r) return;
	int m=l+r>>1;
	if(l==r) {
		Fork(i,l,r) {
			ans.pb(mp(2,pa[i].se));
		}
		Fork(j,now+1,pa[l].fi-1) ans.pb(mp(1,j));
		return;	
	}
	if(m+1<=r) {
		Fork(i,m+1,r) {
			ans.pb(mp(2,pa[i].se));
		}
		Fork(j,now+1,pa[m+1].fi-1) ans.pb(mp(1,j));
		work(m+1,r,pa[m+1].fi);
	}
	if(l<=m) {
		work(l,m,now);
	}
}
int b[1010]={};
int main()
{
	
	n=read();
	For(i,n) a[i]=read();
	For(i,n) pa[i]=mp(a[i],i);
	sort(pa+1,pa+1+n);  
	work(1,n,0);
	for(auto i:ans) {
		if(i.fi==1) {
			For(j,n) if(b[j]==i.se) ++b[j];
		}else{
			b[i.se]++;
		}
	
	}
//	For(i,n) if(a[i]!=b[i]) cout<<"z";

	cout<<SI(ans)<<endl;
	for(auto i:ans) cout<<i.fi<<' '<<i.se<<endl;
	return 0;
}


F Gift

Given an undirected graph with n vertices and n edges, you need to calculate how many ways there are to choose a vertex p and an edge (x, y) such that, after removing the edge (x, y), the graph becomes a
tree, and when this tree is rooted at p, each node has no more than 3 children. It is guaranteed that there
is at least one possible plan

找出环,然后枚举删的边

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 

#define MAXN (212345)
int n,deg[MAXN]={},deg2[MAXN]={};
vi v[MAXN];
int c[MAXN]={};
int main()
{
//	freopen("f.in","r",stdin);
//	freopen(".out","w",stdout);
	
	
	n=read();
	For(i,n) {
		int x=read(),y=read();
		v[x].pb(y); v[y].pb(x);
		deg[x]++;deg[y]++;
	}
	
	queue<int> q;
	For(i,n) if(deg[i]==1) q.push(i);
	For(i,n) deg2[i]=deg[i],c[deg[i]]++;
	
	while(!q.empty()) {
		int x=q.front();
		for(auto y:v[x]) {
			if(deg[y]) {
				--deg[y];
				if(deg[y]==1) q.push(y);
			}
		}
		q.pop();
		deg[x]=0;
	}
	ll ans=0;
	For(i,n) for(auto j:v[i]) if(i<j && deg[i]>0 && deg[j]>0 ){
		c[deg2[i]]--,c[deg2[j]]--;
		c[deg2[i]-1]++,c[deg2[j]-1]++;
		
		if(!c[5]) {
			ans+=n-c[5]-c[4];
		}
		c[deg2[i]]++,c[deg2[j]]++;
		c[deg2[i]-1]--,c[deg2[j]-1]--;
		
	}
	cout<<ans<<endl;
	return 0;
}


G Gene

在这里插入图片描述
经典trick字符串双hash,二分找下一个不同的位置

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 

const int L = 6e4 + 5;
const int HASH_CNT = 2;

int hashBase[HASH_CNT] = {29, 31};
int hashMod[HASH_CNT] = {int(1e9 + 9), 998244353};

struct StringWithHash {
  char s[L];
  int ls;
  int hsh[HASH_CNT][L];
  int pwMod[HASH_CNT][L];

  void init() {  // 初始化
    ls = 0;
    for (int i = 0; i < HASH_CNT; ++i) {
      hsh[i][0] = 0;
      pwMod[i][0] = 1;
    }
  }

  StringWithHash() { init(); }

  void extend(char c) {
    s[++ls] = c;                          // 记录字符数和每一个字符
    for (int i = 0; i < HASH_CNT; ++i) {  // 双哈希的预处理
      pwMod[i][ls] =
          1ll * pwMod[i][ls - 1] * hashBase[i] % hashMod[i];  // 得到b^ls
      hsh[i][ls] = (1ll * hsh[i][ls - 1] * hashBase[i] + c) % hashMod[i];
    }
  }

  vector<int> getHash(int l, int r) {  // 得到哈希值 字符串从1开始计数
    vector<int> res(HASH_CNT, 0);
    for (int i = 0; i < HASH_CNT; ++i) {
      int t =
          (hsh[i][r] - 1ll * hsh[i][l - 1] * pwMod[i][r - l + 1]) % hashMod[i];
      t = (t + hashMod[i]) % hashMod[i];
      res[i] = t;
    }
    return res;
  }
};

bool equal(const vector<int> &h1, const vector<int> &h2) {
  assert(h1.size() == h2.size());
  for (unsigned i = 0; i < h1.size(); i++)
    if (h1[i] != h2[i]) return false;
  return true;
}

int n,q,m,k;
StringWithHash s[310],t;
int calc(int i) {
	int l=1,K=k;
	do{
		int L=l,R=m,ans=L-1;
		while(L<=R) {
			int M=L+R>>1;
			if(equal(t.getHash(L, M),s[i].getHash(L, M)) ) {
				ans=M,L=M+1;
			}else R=M-1;
		}
//		cout<<"|"<<ans<<'|'<<" ";
		if(ans==m) return 1;
		if(K==0) return 0;
		l=ans+2;
		if(l>m) return 1;
		--K;
	}while(1);
	return 0;
}
int main()
{
//	freopen("G.in","r",stdin);
//	freopen(".out","w",stdout);
	cin>>n>>q>>m>>k;
	For(i,n) {
		string st;cin>>st;
		Rep(j,m) s[i].extend(st[j]);
	}
	For(i,q) {
		string st;cin>>st;
		t.init();
		Rep(j,m) t.extend(st[j]);
		int ans=0;
		For(j,n) {
			int p=calc(j);
//			cout<<p;
			ans+=p;
			
		}
		cout<<ans<<endl;
	}
	
	
	return 0;
}


  • 23
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值