CUGBACM23级小学期训练补题

训练1

B - 国王游戏

//lyc
#include <bits/stdc++.h>
#define ll long long 
using namespace std;
int sum[1000001];

int n;
struct node {//贪心
	int a,b;
	bool operator<(const node &x) const{
		return max(x.b,a*b)<max(b,x.a*x.b);
	}
}c[1010];
int len=1;

void multip(ll x){//高精乘
	for(int i=1;i<=len;++i){
		sum[i] *= x;
	}
	for(int i=1;i<=len;++i){
		sum[i+1] += sum[i]/10;
		sum[i]%=10;
	}
	len++;
	while(sum[len]/10){
		sum[len+1]=sum[len]/10;
		sum[len]%=10;
		len++;
	}
	while(sum[len]==0){
		len--;
	}
}

void div(){
	for(int i=len;i>=1;--i){
		sum[i-1]+=(sum[i]%c[n].b*10);
		sum[i]/=c[n].b;
	}
	while(sum[len]==0){
		len--;
	}
}

int main()
{
	sum[1]=1;
	cin>>n;
	cin>>c[0].a>>c[0].b;
	for(int i=1;i<=n;++i){
		cin>>c[i].a>>c[i].b;
	}
	sort(c+1,c+1+n);
	for(int i=0;i<n;++i){
		multip(c[i].a);
	}
	div();
	if(n==1){
		cout<<0;
		exit(0);
	}
	if(len==0){
		cout<<1;
		exit(0);
	}
	
	for(int i=len;i>=1;--i){
		cout<<sum[i];
	}
	return 0;
}

G - 分组

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int cnt;
int q[N];
int siz[N];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin >> n;
	for(int i=1;i<=n;++i){
		cin >> a[i];
	}
	sort(a+1,a+1+n);
	for(int i=1; i<=n; ++i){
		int pos=lower_bound(q+1,q+1+cnt,a[i]-1) - q;
		while(q[pos+1]==q[pos] && pos<cnt){
			pos++;
		}
		if(pos>cnt || q[pos]!=a[i]-1){
			siz[++cnt]=1;
			q[cnt]=a[i];
		}else{
			siz[pos]++;
			q[pos]++;
		}
	}
	int ans=0x3f3f3f3f;
	for(int i=1;i<=cnt;++i){
		ans=min(ans,siz[i]);
	}
	cout<<ans<<'\n';
	return 0;
}

J - ABA and BAB

//lyc
#include <bits/stdc++.h>
#define ll long long 
using namespace std;
const int mod=1e9+7; 
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin>>n;
	string s;
	cin>>s;
	int len=s.size();
	int l=0;
	ll ans=1;
	for(int i=1;i<len;++i){
		if(s[i]!=s[i-1]){
			l++;
		}else{
			if(l>=1){
				ans*=(l+2)/2;
				ans%=mod;
				l=0;
			}
		}
	}
	if(l>=1){
		ans*=(l+2)/2;
		ans%=mod;
	}
	cout<<ans<<'\n';
	return 0;
 } 

K - Water Tank

//lyc
#include <bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=2e5+10;
ll h[N];
stack <int> s;
ll sum[N];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>h[i];
	}
	for(int i=1;i<=n;++i){
		while(!s.empty()&&h[s.top()]<=h[i])
			s.pop();
		if(s.empty()){
			sum[i]=i*h[i];
		}else{
			sum[i]=sum[s.top()]+(i-s.top())*h[i];
		}
		cout<<sum[i]+1<<' ';
		s.push(i);
	}
	return 0;
}

O - Update Queries

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N];
char c[N];
void solve(){
   int n,m;
   cin>>n>>m;
   string s;
   cin>>s;
   map <int,int > mp;
   for(int i=1;i<=m;++i){
   	cin>>a[i];
   	mp[a[i]]=1;
   }
   for(int i=1;i<=m;++i){
   	cin>>c[i];
   }
   sort(c+1,c+1+m);
   int tot=1;
   for(auto i:mp){
   	int pos=i.first;
   	s[pos-1]=c[tot++];
   }
   cout<<s<<'\n';
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int t;
   cin>>t;
   while(t--){
   	solve();
   }
   return 0;
}

P - Mathematical Problem

//lyc
#include <bits/stdc++.h>
#define ll long long 
using namespace std;
ll a[25];
ll dp[25][2];
void solve()
{
	int n;
	cin>>n;
	string s;
	cin>>s;
	for(int i=1;i<=n;++i){
		a[i]=s[i-1]-'0';
	}
	dp[1][0]=a[1];
	dp[2][0]=min(a[1]+a[2],a[1]*a[2]);
	dp[2][1]=a[1]*10+a[2];
	for(int i=3;i<=n;++i){
		dp[i][0]=min(dp[i-1][0]+a[i],dp[i-1][0]*a[i]);
		dp[i][1]=min({dp[i-1][1]+a[i],dp[i-1][1]*a[i],dp[i-2][0]+a[i-1]*10+a[i],dp[i-2][0]*(a[i-1]*10+a[i])});
	}
	cout<<dp[n][1]<<'\n';
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

训练2

D - 星球大战

//lyc
#include <bits/stdc++.h>
using namespace std;
int n,m;
const int N=4e5+10;
int fa[N];
void init(){
	for(int i=1;i<=n;++i){
		fa[i]=i;
	}
}
struct edge{
	int to;
	int nxt;
	int from;
}e[N];
int cnt;
int head[N];
void add(int u,int v){
	e[++cnt].from=u;
	e[cnt].to=v;
	e[cnt].nxt=head[u];
	head[u]=cnt;
}
int k;
int b[N];
bool tag[N];
int find(int x){
	if(fa[x]==x) return x;
	return fa[x]=find(fa[x]);
}
int ans[N];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	init();
	for(int i=1;i<=m;++i){
		int x,y;
		cin>>x>>y;
		add(x,y);
		add(y,x);
	}
	cin>>k;
	int tot=n-k;
	for(int i=1;i<=k;++i){
		int x;
		cin>>x;
		tag[x]=1;
		b[i]=x;
	}
	for(int i=1;i<=2*m;++i){
		if(!tag[e[i].from] && !tag[e[i].to]){
			if(fa[find(e[i].from)]!=find(e[i].to)){
				fa[find(e[i].from)]=find(e[i].to);
				tot--;
			}
		}	
	}
	ans[k]=tot;
	for(int i=k;i>=1;--i){//回溯 倒着修复点 
		tag[b[i]]=0;
		int u=b[i];
		tot++;
		for(int j=head[u];j;j=e[j].nxt){
			int v=e[j].to;
			if(!tag[v] && fa[find(u)]!=find(v)){
				tot--;
				fa[find(u)]=find(v);
			}
		}
		ans[i-1]=tot;
		
	}
	for(int i=0;i<=k;++i){
		cout<<ans[i]<<'\n';
	}
	return 0;
 } 

F - 食物链

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=5e4+10;
int fa[N*3];//x为本身,x+n为x的猎物,x+2*n为x的天敌
int n,k;
void init(){
   for(int i=1;i<=3*n;++i){
   	fa[i]=i;
   }
}
int find(int x){
   if(fa[x]==x) return x;
   return fa[x]=find(fa[x]);
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n>>k;
   init();
   int ans=0;
   while(k--){
   	int op,x,y;
   	cin>>op>>x>>y;
   	if(x>n||y>n){
   		ans++;
   		continue;
   	}
   	if(op==1){
   		if(find(x+n)==find(y)||find(x+2*n)==find(y))
   			ans++;
   		else{
   			fa[find(x)]=find(y);
   			fa[find(x+n)]=find(y+n);
   			fa[find(x+2*n)]=find(y+2*n);
   		}
   	}
   	else{
   		if(find(x)==find(y)||find(x+2*n)==find(y))
   			ans++;
   		else{
   			fa[find(x+n)]=find(y);//x的猎物为y的同类 
   			fa[find(x)]=find(y+2*n);//x的同类是y的天敌 
   			fa[find(x+2*n)]=find(y+n);//x的天敌是y的猎物 
   		}
   	}
   }
   cout<<ans<<'\n'; 
   return 0;
}

L - HH的项链

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,m;
int tr[N];
int a[N];
int vis[N];
struct que{
   int l,r,id;
}q[N];
bool cmp(que a,que b){
   return a.r<b.r;
}
int lowbit(int x){
   return x&-x;
}
void add(int x,int k){
   for(;x<=n;x+=lowbit(x)){
   	tr[x]+=k;
   }
}
int query(int x){
   int ans=0;
   for(;x;x-=lowbit(x)){
   	ans+=tr[x];
   }
   return ans;
}
int ans[N];
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n;
   for(int i=1;i<=n;++i){
   	cin>>a[i];
   }
   cin>>m;
   for(int i=1;i<=m;++i){
   	cin>>q[i].l>>q[i].r;
   	q[i].id=i;
   }
   sort(q+1,q+1+m,cmp);
   int p=1;
   for(int i=1;i<=m;++i){
   	for(int j=p;j<=q[i].r;++j){
   		if(vis[a[j]]) 
   			add(vis[a[j]],-1);
   		add(j,1);
   		vis[a[j]]=j;
   	}
   	p=q[i].r+1;
   	ans[q[i].id]=query(q[i].r)-query(q[i].l-1);
   }
   for(int i=1;i<=m;++i){
   	cout<<ans[i]<<'\n';
   }
   return 0;
}

训练3

A - Max Sum Plus Plus

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N];
int dp[N];
int maxx[N];
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int n,m;
   int mm;
   while(cin>>m>>n){
   	for(int i=1;i<=n;++i){
   		cin>>a[i];
   	}
   	memset(dp,0,sizeof(dp));
   	memset(maxx,0,sizeof(maxx));
   	for(int i=1;i<=m;++i){
   		mm=-0x3f3f3f3f;
   		for(int j=i;j<=n;++j){
   			dp[j]=max(dp[j-1]+a[j],maxx[j-1]+a[j]);
   			//maxx[j-1]目前代表的是分成i-1组前j-1个数的最大值,a[j]单独一组组成i组
   			//dp[j-1]代表j-1个数分成组,第j个数a[j]放在前面i组的一组中,两种方式选取较大者
   			maxx[j-1]=mm;
   			mm=max(mm,dp[j]);
   			
   		}
   	}
   	cout<<mm<<'\n';
   } 
   return 0;
}

G - 免费馅饼

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+100;
int dp[N][20];
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int n;
   while(cin>>n&&n){
   	memset(dp,0,sizeof(dp));
   	int mt=-1e8;
   	for(int i=1;i<=n;++i){
   		int x,t;
   		cin>>x>>t;
   		dp[t][x]++;
   		mt=max(mt,t);
   	}
   	for(int i=mt-1;i>=0;--i){
   		for(int j=0;j<=10;++j){
   			dp[i][j]+=max({dp[i+1][j-1],dp[i+1][j],dp[i+1][j+1]});
   		}
   	}
   	cout<<dp[0][5]<<'\n';
   }
   return 0;
}

H - Tickets

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=2500;
int dp[N];
int s[N],d[N];
void solve(){
   int n;
   cin>>n;
   memset(s,0,sizeof(s));
   memset(d,0,sizeof(d));
   memset(dp,0,sizeof(dp));
   for(int i=1;i<=n;++i){
   	cin>>s[i];
   }
   for(int i=1;i<n;++i){
   	cin>>d[i];
   }
   dp[1]=s[1];
   dp[2]=min(dp[1]+s[2],d[1]);
   for(int i=3;i<=n;++i){
   	dp[i]=min(dp[i-1]+s[i],dp[i-2]+d[i-1]);
   }
   int ans=dp[n];
   int sec=ans%60;
   ans/=60;
   int minute=ans%60;
   int h=ans/60+8;
   h%=24;
   if(h<=12)
   	cout<<setfill('0')<<setw(2)<<h<<':'<<setw(2)<<minute<<':'<<setw(2)<<sec<<" am\n";
   else
   	cout<<setfill('0')<<setw(2)<<h<<':'<<setw(2)<<minute<<':'<<setw(2)<<sec<<" pm\n";
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int t;
   cin>>t;
   while(t--){
   	solve();
   }
   return 0;
}

J - FatMouse’s Speed

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=1010;
int dp[N];
struct mice{
   int w,v,id;
}m[N];
bool cmp(mice a,mice b){
   if(a.w==b.w) return a.v>b.v;
   return a.w<b.w;
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int w,v;
   int cnt=0;
   while(cin>>w>>v){
   	m[++cnt].w=w;
   	m[cnt].v=v;
   	m[cnt].id=cnt;
   }
   sort(m+1,m+1+cnt,cmp);
   int n=0;
   for(int i=cnt;i>=1;--i){
   	dp[i]=1;
   	for(int j=i+1;j<=cnt;++j){
   		if(m[j].w>m[i].w&&m[j].v<m[i].v){
   			dp[i]=max(dp[i],dp[j]+1);
   		}
   	}
   	n=max(n,dp[i]);
   }
   cout<<n<<'\n';
   for(int i=1;i<=cnt;++i){
   	if(dp[i]==n){
   		cout<<m[i].id<<'\n';
   		n--;
   	}
   	if(n==0) break;
   }
   return 0;
}

训练4

E - 绿豆蛙的归宿

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct edge{
   int nxt,v,w;
}e[N<<1];
int head[N];
int in[N],dg[N];
double dp[N];
int cnt;
void add(int u,int v,int w){
   e[++cnt].v=v;
   e[cnt].w=w;
   e[cnt].nxt=head[u];
   head[u]=cnt;
}
int n,m;
void toposort(){
   queue <int> q;
   q.push(n); 
   while(!q.empty()){
   	int u=q.front();
   	q.pop();
   	for(int i=head[u];i;i=e[i].nxt){
   		int v=e[i].v;
   		dp[v]+=(dp[u]+e[i].w)/dg[v];
   		in[v]--;
   		if(!in[v]) q.push(v);
   	}
   }
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n>>m;
   for(int i=1;i<=m;++i){
   	int u,v,w;
   	cin>>u>>v>>w;
   	add(v,u,w);
   	in[u]++;
   	dg[u]++;
   }
   toposort();
   cout<<fixed<<setprecision(2)<<dp[1]<<'\n';
   return 0;
}

G - STA-Station

//lyc
#include <bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=1e6+10;
struct edge{
   int to,nxt;
}e[N<<1];
int cnt,n;
ll head[N];
ll dp[N];
ll siz[N],dep[N];
void add(int u,int v){
   e[++cnt].to=v;
   e[cnt].nxt=head[u];
   head[u]=cnt;
}
void dfs1(int x,int fa){
   siz[x]=1;
   dep[x]=dep[fa]+1;
   for(int i=head[x];i;i=e[i].nxt){
   	int y=e[i].to;
   	if(y==fa) continue;
   	dfs1(y,x);
   	siz[x]+=siz[y];
   }
}
void dfs2(int x,int fa){
   for(int i=head[x];i;i=e[i].nxt){
   	int y=e[i].to;
   	if(y==fa) continue;
   	dp[y]=dp[x]+n-2*siz[y];
   	dfs2(y,x);
   }
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n;
   for(int i=1;i<n;++i){
   	int u,v;
   	cin>>u>>v;
   	add(u,v);
   	add(v,u);
   }
   dfs1(1,0);
   for(int i=1;i<=n;++i){
   	dp[1]+=dep[i];
   }
   dfs2(1,0);
   ll ans=0;
   int id=0;
   for(int i=1;i<=n;++i){
   	if(ans<dp[i]){
   		ans=dp[i];
   		id=i;
   	}
   }
   cout<<id<<'\n';
   return 0;
}

H - 选课

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=350;
int dp[N][N];//dp[i][j]表示以i为根的子树中j个结点 
int head[N];
int cnt;
int val[N];
struct edge{
   int v,nxt;
}e[N<<1];
void add(int u,int v){
   e[++cnt].v=v;
   e[cnt].nxt=head[u];
   head[u]=cnt;
}
void dfs(int u,int tot){
   if(tot==0) return ;
   for(int i=head[u];i;i=e[i].nxt){
   	int v=e[i].v;
   	for(int j=0;j<tot;++j)
   		dp[v][j]=dp[u][j]+val[v];
   	dfs(v,tot-1);
   	for(int j=1;j<=tot;++j)
   		dp[u][j]=max(dp[u][j],dp[v][j-1]);
   }
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int n,m;
   cin>>n>>m;
   for(int i=1;i<=n;++i){
   	int k;
   	cin>>k>>val[i];
   	add(k,i);
   }
   dfs(0,m); 
   cout<<dp[0][m]<<'\n';
   return 0;
}

训练5

E - AC 自动机(简单版)

//lyc
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int trie[N][27];
int fail[N];//失配指针
int cnt;//Trie的指针
int val[N];//标记有几个单词以这个节点结尾 
int getnum(char c){
	return c-'a';
}
void build(string s){//构造trie树
	int l=s.size();
	int p=0;
	for(int i=0;i<l;++i){
		int x=getnum(s[i]);
		if(!trie[p][x])
			trie[p][x]= ++cnt;
		p=trie[p][x];
	}
	val[p]++;
}
queue <int> q;
void getfail(){//bfs求fail指针 
	for(int i=0;i<26;++i){//第二层的fail指针提前处理一下
		if(trie[0][i]){
			fail[trie[0][i]]=0;
			q.push(trie[0][i]);
		}
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=0;i<26;++i){
			if(trie[u][i]){
				fail[trie[u][i]]=trie[fail[u]][i];
                 //子节点的fail指针指向当前节点的
                 //fail指针所指向的节点的相同子节点 
				q.push(trie[u][i]);
			}
			else 
				trie[u][i]=trie[fail[u]][i];
            	//当前节点的这个子节点指向当
                //前节点fail指针的这个子节点 
		}
	}
}
int query(string s){
	int l=s.size();
	int p=0;
	int ans=0;
	for(int i=0;i<l;++i){
		int x=getnum(s[i]);
		p=trie[p][x];
		for(int t=p;t&&val[t]!=-1;t=fail[t]){
			ans+=val[t];
			val[t]=-1;
		}
	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	cin>>n;
	for(int i=1;i<=n;++i){
		string s;
		cin>>s;
		build(s);
	}
	getfail();
	string s;
	cin>>s;
	cout<<query(s)<<'\n';
	return 0;
}

F - AC 自动机(简单版 II)

#include <bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int cnt[N];
string s[N];
int trie[N][26];
int id[N];
int fail[N];
int tot;
int getnum(char c){
	return c-'a';
}
void build(string str,int t){
	int p=0;
	int l=str.size();
	for(int i=0;i<l;++i){
		int x=getnum(str[i]);
		if(!trie[p][x])
			trie[p][x]= ++tot;
		p=trie[p][x];
	}
	id[p]=t;
}
void getfail(){
	queue <int> q;
	int p=0;
	for(int i=0;i<26;++i){
		if(trie[0][i]){
			fail[trie[0][i]]=0;
			q.push(trie[0][i]);
		}
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=0;i<26;++i){
			int v=trie[u][i];
			if(v){
				fail[v]=trie[fail[u]][i];
				q.push(v);
			}
			else
				trie[u][i]=trie[fail[u]][i];
		}	
	}
}
void query(string t){
	int l=t.size();
	int p=0;
	for(int i=0;i<l;++i){
		int x=getnum(t[i]);
		p=trie[p][x];
		for(int j=p;j;j=fail[j]){
			cnt[id[j]]++;
		}
	}
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	while(cin>>n&&n){
		memset(trie,0,sizeof(trie));
		memset(fail,0,sizeof(fail));
		memset(cnt,0,sizeof(cnt));
		memset(id,0,sizeof(id));
		tot=0;
		for(int i=1;i<=n;++i){
			cin>>s[i];
			build(s[i],i);
		}
		getfail();
		string t;
		cin>>t;
		query(t);
		int maxx=0;
		for(int i=1;i<=n;++i){
			maxx=max(maxx,cnt[i]);
		}
		cout<<maxx<<'\n';
		for(int i=1;i<=n;++i){
			if(cnt[i]==maxx)
				cout<<s[i]<<'\n';
		}
	}
	return 0;
}

G - AC 自动机

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int trie[N][26];
int in[N];
int tot;
int cnt[N];
int fail[N];
int id[N];
int getnum(char c){
   return c-'a';
}
int flag[N];
void build(string s,int t){
   int p=0;
   int l=s.size();
   for(int i=0;i<l;++i){
   	int x=getnum(s[i]);
   	if(!trie[p][x])
   		trie[p][x]= ++tot;
   	p=trie[p][x];
   }
   if(!flag[p]) flag[p]=t;
   id[t]=flag[p]; 
}
queue <int> q;
void getfail(){
   int p=0;
   for(int i=0;i<26;++i){
   	if(trie[0][i]){
   		fail[trie[0][i]]=0;
   		q.push(trie[0][i]);
   	}
   }
   while(!q.empty()){
   	int u=q.front();
   	q.pop();
   	for(int i=0;i<26;++i){
   		int v=trie[u][i];
   		if(v){
   			fail[v]=trie[fail[u]][i];
   			q.push(v);
   			in[fail[v]]++;
   		}
   		else 
   			trie[u][i]=trie[fail[u]][i];
   	}
   }
}
int tag[N];
void query(string s){
   int p=0;
   int l=s.size();
   for(int i=0;i<l;++i){
   	int x=getnum(s[i]);
   	p=trie[p][x];
   	tag[p]++;
   }
}
void topo(){
   for(int i=1;i<=tot;++i){
   	if(!in[i])
   		q.push(i);
   }
   while(!q.empty()){
   	int u=q.front();
   	q.pop();
   	cnt[flag[u]]=tag[u];
   	int v=fail[u];
   	in[v]--;
   	tag[v]+=tag[u];
   	if(in[v]==0)
   		q.push(v);
   }
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int n;
   cin>>n;
   for(int i=1;i<=n;++i){
   	string s;
   	cin>>s;
   	build(s,i);
   }
   getfail();
   string t;
   cin>>t;
   query(t);
   topo();
   for(int i=1;i<=n;++i){
   	cout<<cnt[id[i]]<<'\n';
   }
   return 0;
} 

训练6

B - 魔方

#include <bits/stdc++.h>
using namespace std;
int a[6][3][3],b[6][3][3];
char s[101];
int main(){
   
   cin>>s;
   for(int i=0;i<6;++i)
   	for(int j=0;j<3;++j)
   		for(int k=0;k<3;++k)
   			scanf("%1d",a[i][j]+k);
   for(int i=0;i<strlen(s);++i){
   	switch(s[i]){
   		case '1':
   			b[0][0][2]=a[5][0][2];
   			b[0][1][2]=a[5][1][2];
   			b[0][2][2]=a[5][2][2];
   			b[1][0][2]=a[4][0][2];
   			b[1][1][2]=a[4][1][2];
   			b[1][2][2]=a[4][2][2];
   			b[3][0][2]=a[3][0][0];
   			b[3][1][2]=a[3][0][1];
   			b[3][2][2]=a[3][0][2];
   			b[3][0][1]=a[3][1][0];
   			b[3][1][1]=a[3][1][1];
   			b[3][2][1]=a[3][1][2];
   			b[3][0][0]=a[3][2][0];
   			b[3][1][0]=a[3][2][1];
   			b[3][2][0]=a[3][2][2];
   			b[4][0][2]=a[0][0][2];
   			b[4][1][2]=a[0][1][2];
   			b[4][2][2]=a[0][2][2];
   			b[5][0][2]=a[1][0][2];
   			b[5][1][2]=a[1][1][2];
   			b[5][2][2]=a[1][2][2];
               
   			a[0][0][2]=b[0][0][2];
   			a[0][1][2]=b[0][1][2];
   			a[0][2][2]=b[0][2][2];
   			a[1][0][2]=b[1][0][2];
   			a[1][1][2]=b[1][1][2];
   			a[1][2][2]=b[1][2][2];
   			a[3][0][2]=b[3][0][2];
   			a[3][1][2]=b[3][1][2];
   			a[3][2][2]=b[3][2][2];
   			a[3][0][1]=b[3][0][1];
   			a[3][1][1]=b[3][1][1];
   			a[3][2][1]=b[3][2][1];
   			a[3][0][0]=b[3][0][0];
   			a[3][1][0]=b[3][1][0];
   			a[3][2][0]=b[3][2][0];
   			a[4][0][2]=b[4][0][2];
   			a[4][1][2]=b[4][1][2];
   			a[4][2][2]=b[4][2][2];
   			a[5][0][2]=b[5][0][2];
   			a[5][1][2]=b[5][1][2];
   			a[5][2][2]=b[5][2][2];
   			break;
   		case '2':
   			b[0][0][2]=a[4][0][2];
   			b[0][1][2]=a[4][1][2];
   			b[0][2][2]=a[4][2][2];
   			b[1][0][2]=a[5][0][2];
   			b[1][1][2]=a[5][1][2];
   			b[1][2][2]=a[5][2][2];
   			b[3][2][0]=a[3][0][0];
   			b[3][1][0]=a[3][0][1];
   			b[3][0][0]=a[3][0][2];
   			b[3][2][1]=a[3][1][0];
   			b[3][1][1]=a[3][1][1];
   			b[3][0][1]=a[3][1][2];
   			b[3][2][2]=a[3][2][0];
   			b[3][1][2]=a[3][2][1];
   			b[3][0][2]=a[3][2][2];
   			b[4][0][2]=a[1][0][2];
   			b[4][1][2]=a[1][1][2];
   			b[4][2][2]=a[1][2][2];
   			b[5][0][2]=a[0][0][2];
   			b[5][1][2]=a[0][1][2];
   			b[5][2][2]=a[0][2][2];
   			
               a[0][0][2]=b[0][0][2];
   			a[0][1][2]=b[0][1][2];
   			a[0][2][2]=b[0][2][2];
   			a[1][0][2]=b[1][0][2];
   			a[1][1][2]=b[1][1][2];
   			a[1][2][2]=b[1][2][2];
   			a[3][0][2]=b[3][0][2];
   			a[3][1][2]=b[3][1][2];
   			a[3][2][2]=b[3][2][2];
   			a[3][0][1]=b[3][0][1];
   			a[3][1][1]=b[3][1][1];
   			a[3][2][1]=b[3][2][1];
   			a[3][0][0]=b[3][0][0];
   			a[3][1][0]=b[3][1][0];
   			a[3][2][0]=b[3][2][0];
   			a[4][0][2]=b[4][0][2];
   			a[4][1][2]=b[4][1][2];
   			a[4][2][2]=b[4][2][2];
   			a[5][0][2]=b[5][0][2];
   			a[5][1][2]=b[5][1][2];
   			a[5][2][2]=b[5][2][2];
   			break;
   		case '3':
   			b[0][0][0]=a[2][0][0];
   			b[0][0][1]=a[2][0][1];
   			b[0][0][2]=a[2][0][2];
   			b[1][0][0]=a[3][0][0];
   			b[1][0][1]=a[3][0][1];
   			b[1][0][2]=a[3][0][2];
   			b[2][0][0]=a[1][0][0];
   			b[2][0][1]=a[1][0][1];
   			b[2][0][2]=a[1][0][2];
   			b[3][0][0]=a[0][0][0];
   			b[3][0][1]=a[0][0][1];
   			b[3][0][2]=a[0][0][2];
   			b[4][0][2]=a[4][0][0];
   			b[4][1][2]=a[4][0][1];
   			b[4][2][2]=a[4][0][2];
   			b[4][0][1]=a[4][1][0];
   			b[4][1][1]=a[4][1][1];
   			b[4][2][1]=a[4][1][2];
   			b[4][0][0]=a[4][2][0];
   			b[4][1][0]=a[4][2][1];
   			b[4][2][0]=a[4][2][2];
               
   			a[0][0][0]=b[0][0][0];
   			a[0][0][1]=b[0][0][1];
   			a[0][0][2]=b[0][0][2];
   			a[1][0][0]=b[1][0][0];
   			a[1][0][1]=b[1][0][1];
   			a[1][0][2]=b[1][0][2];
   			a[2][0][0]=b[2][0][0];
   			a[2][0][1]=b[2][0][1];
   			a[2][0][2]=b[2][0][2];
   			a[3][0][0]=b[3][0][0];
   			a[3][0][1]=b[3][0][1];
   			a[3][0][2]=b[3][0][2];
   			a[4][0][2]=b[4][0][2];
   			a[4][1][2]=b[4][1][2];
   			a[4][2][2]=b[4][2][2];
   			a[4][0][1]=b[4][0][1];
   			a[4][1][1]=b[4][1][1];
   			a[4][2][1]=b[4][2][1];
   			a[4][0][0]=b[4][0][0];
   			a[4][1][0]=b[4][1][0];
   			a[4][2][0]=b[4][2][0];
   			break;
   		case '4':
   			b[0][0][0]=a[3][0][0];
   			b[0][0][1]=a[3][0][1];
   			b[0][0][2]=a[3][0][2];
   			b[1][0][0]=a[2][0][0];
   			b[1][0][1]=a[2][0][1];
   			b[1][0][2]=a[2][0][2];
   			b[2][0][0]=a[0][0][0];
   			b[2][0][1]=a[0][0][1];
   			b[2][0][2]=a[0][0][2];
   			b[3][0][0]=a[1][0][0];
   			b[3][0][1]=a[1][0][1];
   			b[3][0][2]=a[1][0][2];
   			b[4][2][0]=a[4][0][0];
   			b[4][1][0]=a[4][0][1];
   			b[4][0][0]=a[4][0][2];
   			b[4][2][1]=a[4][1][0];
   			b[4][1][1]=a[4][1][1];
   			b[4][0][1]=a[4][1][2];
   			b[4][2][2]=a[4][2][0];
   			b[4][1][2]=a[4][2][1];
   			b[4][0][2]=a[4][2][2];
               
   			a[0][0][0]=b[0][0][0];
   			a[0][0][1]=b[0][0][1];
   			a[0][0][2]=b[0][0][2];
   			a[1][0][0]=b[1][0][0];
   			a[1][0][1]=b[1][0][1];
   			a[1][0][2]=b[1][0][2];
   			a[2][0][0]=b[2][0][0];
   			a[2][0][1]=b[2][0][1];
   			a[2][0][2]=b[2][0][2];
   			a[3][0][0]=b[3][0][0];
   			a[3][0][1]=b[3][0][1];
   			a[3][0][2]=b[3][0][2];
   			a[4][0][2]=b[4][0][2];
   			a[4][1][2]=b[4][1][2];
   			a[4][2][2]=b[4][2][2];
   			a[4][0][1]=b[4][0][1];
   			a[4][1][1]=b[4][1][1];
   			a[4][2][1]=b[4][2][1];
   			a[4][0][0]=b[4][0][0];
   			a[4][1][0]=b[4][1][0];
   			a[4][2][0]=b[4][2][0];
   			break;
   	}
   }
   for(int i=0;i<6;++i)
   	for(int j=0;j<3;++j){
   		for(int k=0;k<3;++k)
   			cout<<a[i][j][k];
   		cout<<'\n';
   	}
   return 0;
}

H - Bear and Prime 100

#include <bits/stdc++.h>
using namespace std;
int a[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,4,9,25,49};
int main()
{
   int cnt=0;
   for(int i=0;i<19;++i){
   	cout<<a[i]<<'\n';
   	fflush(stdout);
   	string s;
   	cin>>s;
   	if(s[0]=='y')
   		cnt++;
   }
   if(cnt>=2) cout<<"composite\n";
   else cout<<"prime\n";
   fflush(stdout);
   return 0;
}

I - Bear and Tower of Cubes

#include <bits/stdc++.h>
#define ll long long 
using namespace std;
ll m;
ll f(ll x){
   return x*x*x;
}
ll ansn,ansv;
void dfs(ll m,ll s,ll t){
   if(m==0){
   	if(s>ansn||(s==ansn&&t>ansv)){
   		ansn=s;
   		ansv=t;
   	}
   	return ;
   }
   ll x=1;
   while(f(x+1)<=m)
   	x++;
   dfs(m-f(x),s+1,t+f(x));
   if(x>=1){
   	dfs(f(x)-1-f(x-1),s+1,t+f(x-1));
   }
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>m; 
   dfs(m,0,0);
   cout<<ansn<<' '<<ansv<<'\n';
   return 0;
}

训练7

F - 贴海报

#include <bits/stdc++.h>
using namespace std;
int a[1010],b[1010];
bool vis[1010];
int n,m;
int ans;
void solve(int l,int r,int now,int num){
   if(vis[num]) 
       return ;
   while(now<=m&&(l>=b[now]||r<=a[now]))
   	now++;
   if(now>m){
   	ans++;
   	vis[num]=1;
   }
   if(l<a[now]&&r>a[now])
   	solve(l,a[now],now+1,num);
   if(r>b[now]&&l<b[now]) 
   	solve(b[now],r,now+1,num);
   
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   
   cin>>n>>m;
   for(int i=1;i<=m;++i){
   	cin>>a[i]>>b[i];
   	b[i]++;
   }
   for(int i=m-1;i>=1;--i){
   	solve(a[i],b[i],i+1,i);
   } 
   cout<<ans+1<<'\n';
   return 0;
}

I - HH的项链

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,m;
int tr[N];
int a[N];
int vis[N];
struct que{
   int l,r,id;
}q[N];
bool cmp(que a,que b){
   return a.r<b.r;
}
int lowbit(int x){
   return x&-x;
}
void add(int x,int k){
   for(;x<=n;x+=lowbit(x)){
   	tr[x]+=k;
   }
}
int query(int x){
   int ans=0;
   for(;x;x-=lowbit(x)){
   	ans+=tr[x];
   }
   return ans;
}
int ans[N];
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n;
   for(int i=1;i<=n;++i){
   	cin>>a[i];
   }
   cin>>m;
   for(int i=1;i<=m;++i){
   	cin>>q[i].l>>q[i].r;
   	q[i].id=i;
   }
   sort(q+1,q+1+m,cmp);
   int p=1;
   for(int i=1;i<=m;++i){
   	for(int j=p;j<=q[i].r;++j){
   		if(vis[a[j]]) 
   			add(vis[a[j]],-1);
   		add(j,1);
   		vis[a[j]]=j;
   	}
   	p=q[i].r+1;
   	ans[q[i].id]=query(q[i].r)-query(q[i].l-1);
   }
   for(int i=1;i<=m;++i){
   	cout<<ans[i]<<'\n';
   }
   return 0;
}

K - 数颜色 / 维护队列

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct que{
   int l,r,t,id;
}qq[N],qr[N];
int cntq,cntr;
int n,m;
int par;
int ans[N];
int pos[N],a[N];
int cnt[1000010];
bool cmp(que a,que b){
//	if(pos[a.l]==pos[b.l]){
//		if(pos[a.r]==pos[a.r]){
//			return a.t<b.t;
//		}else{
//			return pos[a.r]<pos[b.r];
//		}
//	}else{
//		return pos[a.l]<pos[a.l];
//	}
   return a.l / par == b.l / par ? a.r / par == b.r / par ? a.t < b.t : a.r < b.r : a.l < b.l;
}
int sum;
void add(int x){
   cnt[x]++;
   if(cnt[x]==1) sum+=1;
   //sum += !cnt[x]++;
}
void del(int x){
   cnt[x]--;
   if(cnt[x]==0) sum-=1;
   //sum -= !--cnt[x];
}
void update(int x,int t){
   if(qq[x].l<=qr[t].l&&qr[t].l<=qq[x].r){
   	del(a[qr[t].l]);
   	add(qr[t].r);
   }
   swap(a[qr[t].l],qr[t].r);
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n>>m;
   par=(int)pow(n,0.666);
   for(int i=1;i<=n;++i){
   	cin>>a[i];
   	pos[i]=(i-1)/par+1;
   }
   for(int i=1;i<=m;++i){
   	char op;
   	int l,r;
   	cin>>op>>l>>r;
   	if(op=='Q'){
   		qq[++cntq].id=cntq;
   		qq[cntq].l=l;
   		qq[cntq].r=r;
   		qq[cntq].t=cntr;
   	}else{
   		qr[++cntr].l=l;
   		qr[cntr].r=r;
   	}
   }
   sort(qq+1,qq+1+cntq,cmp);
   int l=1,r=0,t=0;
   for(int i=1;i<=cntq;++i){
   	while(l>qq[i].l)
   		add(a[--l]);
   	while(r<qq[i].r)
   		add(a[++r]);
   	while(l<qq[i].l)
   		del(a[l++]);
   	while(r>qq[i].r)
   		del(a[r--]);
   	while(t<qq[i].t)
   		update(i,++t);
   	while(t>qq[i].t)
   		update(i,t--);
   	ans[qq[i].id]=sum;
   }
   for(int i=1;i<=cntq;++i){
   	cout<<ans[i]<<'\n';
   }
   return 0;
}

训练8

G - Intersecting Lines

#include <bits/stdc++.h>
using namespace std;
const double eps=1e-6;
struct point{
   double x,y;
   point (double x=0,double y=0):x(x),y(y){
   	
   }
};
typedef point vec;

vec operator -(const vec &a, const vec& b){
   	return vec(a.x-b.x,a.y-b.y);
   }
int sgn(double x){//精度
   if(fabs(x)<eps) return 0;
   if(x>0) return 1;
   return -1;
}
//int dcmp(double a,double b){
//	if(fabs(b-a)<eps) return 0;
//	if(a>b) return 1;
//	return -1;
//}
double cross(vec a,vec b){//叉乘
   return a.x*b.y-a.y*b.x;
}
bool online(point a,point b,point c){//判断是否三点共线
   return sgn(cross(b-a,c-a))==0;
}
vec operator *(vec a,double b){
   return vec(a.x*b,a.y*b);
}
vec operator +(vec a,vec b){
   return vec(a.x+b.x,a.y+b.y);
}
point getpoint(point p,vec a,point q,vec b){
   vec u=p-q;
   double t=cross(b,u)/cross(a,b);
   return p+a*t;
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int n;
   cin>>n;
   cout<<"INTERSECTING LINES OUTPUT\n";
   while(n--){
   	point p1,p2,p3,p4;
   	cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y>>p4.x>>p4.y;
   	vec a,b;
   	a=p2-p1;
   	b=p4-p3;
   	if(sgn(cross(a,b))==0){
   		if(online(p1,p3,p4)){
   			cout<<"LINE\n";
   		}else{
   			cout<<"NONE\n";
   		}
   	}
   	else{
   		point p=getpoint(p1,a,p3,b);
   		cout<<"POINT "<<fixed<<setprecision(2)<<p.x<<' '<<setprecision(2)<<p.y<<'\n';
   	}
   }
   cout<<"END OF OUTPUT\n";
   
   
   return 0;
}

H - Pick-up sticks

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n;
struct point{
	double x,y;
};
struct line{
	point p1,p2;
}a[N]; 
double cj(point p1,point p2,point p3){
	return (p1.x-p3.x)*(p2.y-p3.y)-(p1.y-p3.y)*(p2.x-p3.x);
}
int judge(line l1,line l2){
	if(min(l1.p1.x,l1.p2.x)<=max(l2.p1.x,l2.p2.x)&&min(l2.p1.x,l2.p2.x)<=max(l1.p1.x,l1.p2.x)&&min(l1.p1.y,l1.p2.y)<=max(l2.p1.y,l2.p2.y)&&min(l2.p1.y,l2.p2.y)<=max(l1.p1.y,l1.p2.y)&&
	cj(l1.p1,l2.p2,l2.p1)*cj(l1.p2,l2.p2,l2.p1)<=0&&cj(l2.p1,l1.p2,l1.p1)*cj(l2.p2,l1.p2,l1.p1)<=0)
		return 1;
	else 
		return 0;
}
int flag[N];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	while(cin>>n&&n){
		for(int i=1;i<=n;++i){
			cin>>a[i].p1.x>>a[i].p1.y>>a[i].p2.x>>a[i].p2.y;
		}
		memset(flag,0,sizeof(flag));
		for(int i=1;i<n;++i){
			for(int j=i+1;j<=n;++j){
				if(judge(a[i],a[j])){
					flag[i]=1;
					break;
				}
			}
		}
		cout<<"Top sticks: ";
		for(int i=1;i<=n;++i){
			if(flag[i]==0){
				if(i==n){
					cout<<i<<".\n";
				}
				else
					cout<<i<<", ";
			}
		}
	}
	return 0;
}

L - Segments

#include <bits/stdc++.h>
using namespace std;
const double eps=1e-8;
struct point {
	double x,y;
	point (double x=0,double y=0):x(x),y(y){
		
	}
}p[220];
int n;
typedef point vec;
int sgn(double x){
	if(fabs(x)<eps) return 0;
	if(x>eps) return 1;
	return -1;
}
vec operator -(point a,point b){
	return vec(a.x-b.x,a.y-b.y);
}
double cross(vec a,vec b){
	return a.x*b.y-a.y*b.x;
}
bool inter(point a,point b,point c,point d){
	if(sgn(cross(c-a,b-a))*sgn(cross(d-a,b-a))>0)
		return 0;
	else return 1;
}
bool judge(point a,point b){
	if(sgn(a.x-b.x)==0&&sgn(a.y-b.y)==0) return 0;
	for(int i=1;i<=2*n;i+=2){
		if(!inter(a,b,p[i],p[i+1])){
			return 0;
		}
	}
	return 1;
}
void solve(){
	cin>>n;
	for(int i=1;i<=2*n;++i){
		cin>>p[i].x>>p[i].y;
	}
	if(n==1){
		cout<<"Yes!\n";
		return ;
	}
	bool flag=0;
	for(int i=1;i<=2*n;++i){
		for(int j=1;j<=2*n;++j){
			if(judge(p[i],p[j])){
				flag=1;
				break;
			}
		}
		if(flag) break;
	}
	if(flag) cout<<"Yes!\n";
	else cout<<"No!\n";
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

训练9

I - 青蛙的约会

#include <iostream>
#define ll long long 
using namespace std;

ll x1;
ll y0;
ll ans;
void exgcd(ll a,ll b){
	if(!b){
		x1=1;
		//y1=0;
		ans=a;
		return ;
	}
	exgcd(b,a%b);
	ll t=x1;
	x1=y0;
	y0=t-a/b*y0;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	ll n,m,x,y,l;
	cin>>x>>y>>m>>n>>l;
	ll a=n-m;
	ll b=l;
	ll c=x-y;
	if(a<0){
		c=-c;
		a=-a;
	}
	exgcd(a,b);
	if(c%ans!=0){
		cout<<"Impossible\n";
	}else{
		cout<<(c/ans*x1%(b/ans)+b/ans)%(b/ans)<<'\n';
	}
	return 0;
}

训练10

D - 回家的路

#include <bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=2e6+10;
const int M=2e6+10;
struct edge{
	int v,nxt,dis;
}e[M];
struct node{
	int x,y,id;
}a[N];
bool vis[N];
ll dis[N];
int head[N];
int tot;
int n,m;
void add(int u,int v,int dis){
	e[++tot].v=v;
	e[tot].dis=dis;
	e[tot].nxt=head[u];
	head[u]=tot;
} 
bool cmpx(node a,node b){
	if(a.x==b.x) return a.y<b.y;
	return a.x<b.x;
}
bool cmpy(node a,node b){
	if(a.y==b.y) return a.x<b.x;
	return a.y<b.y;
}
void dijkstra(int s){
	priority_queue < pair<int,int> ,vector < pair<int,int> > ,greater <pair <int,int> > > q;
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0;
	q.push({0,s});
	while(!q.empty()){
		int u=q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].v;
			if(dis[v]>dis[u]+e[i].dis){
				dis[v]=dis[u]+e[i].dis;
				if(!vis[v])
					q.push({dis[v],v});
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	n=m+2;
	int s,t;
	s=n-1;
	t=n;
	for(int i=1;i<=n;++i){
		cin>>a[i].x>>a[i].y;
		a[i].id=i;
	}
	sort(a+1,a+1+n,cmpx);
	for(int i=1;i<n;++i){
		if(a[i].x==a[i+1].x){
			add(a[i].id,a[i+1].id,(a[i+1].y-a[i].y)<<1);
			add(a[i+1].id,a[i].id,(a[i+1].y-a[i].y)<<1);
		}
	}
	sort(a+1,a+1+n,cmpy);
	for(int i=1;i<n;++i){
		if(a[i].y==a[i+1].y){
			add(a[i].id+n,a[i+1].id+n,(a[i+1].x-a[i].x)<<1);
			add(a[i+1].id+n,a[i].id+n,(a[i+1].x-a[i].x)<<1);
		}
	}
	for(int i=1;i<=n-2;++i){
		add(i,i+n,1);
		add(i+n,i,1);
	}
	add(s,s+n,0);
	add(s+n,s,0);
	add(t,t+n,0);
	add(t+n,t,0);
	dijkstra(s);
	if(dis[t]==0x3f3f3f3f){
		cout<<-1<<'\n';
	}else{
		cout<<dis[t]<<'\n';
	}
	return 0;
}

E - 缩点

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int n,m;
int top,ptop,cnt,tot;
stack <int> s;
int vis[N],head[N];
int dis[N],in[N];
int dfn[N],low[N];
int sd[N],a[N];//sd[i]表示缩点后点的编号
struct edge {
   int v,nxt,u;
}e[N*10],ed[N*10];
void add(int u,int v){
   e[++cnt].nxt=head[u];
   e[cnt].v=v;
   e[cnt].u=u;
   head[u]=cnt;
}
void tarjan(int x){
   low[x]=dfn[x]=++ptop;
   s.push(x);
   vis[x]=1;
   for(int i=head[x];i;i=e[i].nxt){
   	int v=e[i].v;
   	if(!dfn[v]){
   		tarjan(v);
   		low[x]=min(low[x],low[v]);
   	}
   	else if(vis[v]){
   		low[x]=min(low[x],low[v]);
   	}
   }
   if(low[x]==dfn[x]){
   	int y;
   	while(!s.empty()){
   		y=s.top();
   		s.pop();
   		sd[y]=x;
   		vis[y]=0;
   		if(x==y) break;
   		a[x]+=a[y];
   	}
   }
}
int h[N];
int ans=0;
void topo(){
   queue <int> q;
   for(int i=1;i<=n;++i){
   	if(sd[i]==i&&in[i]==0){
   		q.push(i);
   		dis[i]=a[i];
   	}
   }
   while(!q.empty()){
   	int u=q.front();
   	q.pop();
   	for(int i=h[u];i;i=ed[i].nxt){
   		int v=ed[i].v;
   		dis[v]=max(dis[v],dis[u]+a[v]);
   		in[v]--;
   		if(in[v]==0){
   			q.push(v);
   		}
   	}
   }
   for(int i=1;i<=n;++i){
   	ans=max(ans,dis[i]);
   }
   
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n>>m;
   for(int i=1;i<=n;++i){
   	cin>>a[i];
   }
   for(int i=1;i<=m;++i){
   	int x,y;
   	cin>>x>>y;
   	add(x,y);
   }
   for(int i=1;i<=n;++i){
   	if(!dfn[i]){
   		tarjan(i);
   	}
   } 
   for(int i=1;i<=m;++i){//拓扑图建边
   	int x=sd[e[i].u];
   	int y=sd[e[i].v];
   	if(x!=y){
   		ed[++tot].u=x;
   		ed[tot].v=y;
   		ed[tot].nxt=h[x];
   		h[x]=tot;
   		in[y]++;
   	}
   }
   topo();
   cout<<ans<<'\n';
   return 0;
}

G - ±1

#include <bits/stdc++.h>
using namespace std;
const int N=510;
int n;
int a[N][3];
int id(int x){
   if(x<0)
   	return -x+n;
   return x;
}
int dfn[N<<1],low[N<<1];
int sd[N<<1],vis[N<<1];
int cnt,tot;
vector <int> v[N<<1];
stack <int> s;
void tarjan(int x){
   dfn[x]=low[x]=++tot;

   s.push(x);
   vis[x]=1;
   for(auto e:v[x]){
   	if(!dfn[e]){
   		tarjan(e);
   		low[x]=min(low[x],low[e]);
   	}
   	else if(vis[e]){
   		low[x]=min(low[x],low[e]);
   	}
   }
   if(low[x]==dfn[x]){
   	int y;
   	cnt++;
   	while(!s.empty()){
   		y=s.top();
   		s.pop();
   		sd[y]=cnt;
   		vis[y]=0;
   		if(x==y) break;
   	}
   }
}
void solve(){
   cin>>n;
   for(int j=0;j<3;++j){
   	for(int i=1;i<=n;++i){
   		cin>>a[i][j];
   	}
   }
   cnt=0;
   tot=0;
   for(int i=1;i<=2*n;++i){
   	v[i].clear();
   	dfn[i]=low[i]=sd[i]=0;
   	vis[i]=0;
   }
   int x,y,z;
   for(int i=1;i<=n;++i){
   	x=a[i][0];
   	y=a[i][1];
   	z=a[i][2];
   	v[id(-x)].push_back(id(y));
   	v[id(-x)].push_back(id(z));
   	v[id(-y)].push_back(id(x));
   	v[id(-y)].push_back(id(z));
   	v[id(-z)].push_back(id(x));
   	v[id(-z)].push_back(id(y));
   }
   for(int i=1;i<=2*n;++i){
   	if(!dfn[i])
   		tarjan(i);
   }
   
   bool flag=1;
   for(int i=1;i<=n;++i){
   	if(sd[id(i)]==sd[id(-i)]){
   		flag=0;
   	}
   }
   if(flag) cout<<"YES\n";
   else cout<<"NO\n";
}

int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int t;
   cin>>t;
   while(t--){
   	solve();
   }
   return 0;
}

训练11

G - Divide by three, multiply by two

#include <bits/stdc++.h>
#define ll long long 
using namespace std;
struct node{
   ll a,b;
}c[110];
bool cmp(node x,node y){
   if(x.b==y.b) return x.a<y.a;
   return x.b>y.b;
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int n;
   cin>>n;
   for(int i=1;i<=n;++i){
   	cin>>c[i].a;
   	ll t=c[i].a;
   	while(t%3==0&&t){
   		c[i].b++;
   		t/=3;
   	}
   } 
   sort(c+1,c+1+n,cmp);
   for(int i=1;i<=n;++i){
   	cout<<c[i].a<<' ';
   }
   return 0;
}

H - Coprocessor

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct edge{
	int v,nxt;
}e[N<<1];
int vis[N];
int head[N];
int cnt;
int n,m;
int in[N]; 
void add(int u,int v){
	e[++cnt].v=v;
	e[cnt].nxt=head[u];
	head[u]=cnt;
}
queue <int> q1,q2;
int ans;
void topo(){
	for(int i=1;i<=n;++i){
		if(in[i]==0){
			if(vis[i]==0)
				q1.push(i);
			else 
				q2.push(i);
		}
	}
	while(!q1.empty()||!q2.empty()){
		while(!q1.empty()){
			int u=q1.front();
			q1.pop();
			for(int i=head[u];i;i=e[i].nxt){
				int v=e[i].v;
				in[v]--;
				if(in[v]==0){
					if(vis[v]==0)
						q1.push(v);
					else 
						q2.push(v);
				}
			}
		}
		if(!q2.empty())
			ans++;
		while(!q2.empty()){
			int u=q2.front();
			q2.pop();
			for(int i=head[u];i;i=e[i].nxt){
				int v=e[i].v;
				in[v]--;
				if(in[v]==0){
					if(vis[v]==0){
						q1.push(v);
					}
					else 
						q2.push(v);
				}
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;++i){
		cin>>vis[i];
	}
	for(int i=1;i<=m;++i){
		int x,y;
		cin>>x>>y;
		x++;
		y++;
		add(x,y);
		in[y]++;
	}
	topo();
	cout<<ans<<'\n';
	return 0;
}

L - 树的重心

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n;
vector <int> e[N];
int siz[N],w[N];
//w[i] 此节点的重量 所有子树 大小的最大值
//siz[i] 此节点的大小 所有子树数量加上该节点
int ans1,ans2;

void dfs(int u,int fa){
   siz[u]=1;
   w[u]=0;
   for(auto i:e[u]){
   	if(i!=fa){
   		dfs(i,u);
   		siz[u]+=siz[i];
   		w[u]=max(w[u],siz[i]);
   	}
   }
   w[u]=max(w[u],n-siz[u]);
   if(w[u]<=n/2){
   	ans2=ans1;
   	ans1=u;
   }
}
void solve(){
   cin>>n;
   for(int i=1;i<=n;++i){
   	e[i].clear();
   	siz[i]=w[i]=0;
   }
   for(int i=1;i<n;++i){
   	int x,y;
   	cin>>x>>y;
   	e[x].push_back(y);
   	e[y].push_back(x);
   }
   ans1=ans2=0;
   dfs(1,0);
   if(ans2==0){
   	cout<<ans1<<' '<<e[ans1][0]<<'\n';
   	cout<<ans1<<' '<<e[ans1][0]<<'\n';
   }
   else{
   	int i=0;
   	int len=e[ans1].size();
   	while(ans2==e[ans1][i]&&i<len){
   		i++;
   	}
   	cout<<ans1<<' '<<e[ans1][i]<<'\n';
   	cout<<ans2<<' '<<e[ans1][i]<<'\n';
   }
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int t;
   cin>>t;
   while(t--){
   	solve();
   }
   return 0;
}

N - 重链剖分/树链剖分

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct edge{
   int v,nxt;
}e[N<<1];
int head[N];
int fa[N];//父节点 
int dep[N];//深度 
int son[N];//记录重儿子 
int siz[N];//该节点及其子节点的大小 
int top[N];//每一个节点所属重链的根节点 
int dfn[N];//dfs序 
int w[N];//dfs序后节点的权值,用线段树维护

int sum[N<<2];
int tag[N<<2];
int lpos[N<<2],rpos[N<<2];//线段树区间的左右端点 
int tim,cnt;
int v[N];//所有节点的权值 
int ls(int x){
   return x<<1;
} 
int rs(int x){
   return x<<1|1;
}
void add(int u,int v){
   e[++cnt].v=v;
   e[cnt].nxt=head[u];
   head[u]=cnt;
}
int n,m,r,p;
void dfs1(int u,int f){
   fa[u]=f;
   dep[u]=dep[f]+1;
   siz[u]=1;
   int mm=-1;//记录重儿子的大小
   for(int i=head[u];i;i=e[i].nxt){
   	int v=e[i].v;
   	if(v==f) continue;
   	dfs1(v,u);
   	siz[u]+=siz[v];
   	if(siz[v]>mm){
   		mm=siz[v];
   		son[u]=v;
   	}
   } 
}

void dfs2(int u,int t){
   dfn[u]= ++tim;
   top[u]=t;
   w[tim]=v[u];
   
   if(!son[u]) return ;
   dfs2(son[u],t);
   for(int i=head[u];i;i=e[i].nxt){
   	int v=e[i].v;
   	//重儿子已遍历过 
   	if(v==fa[u]||v==son[u])
   		continue;
   	else//否则以 该节点为新的重链祖先继续dfs序 
   		dfs2(v,v);
   }
   
}

void up(int x){
   sum[x]= sum[ls(x)]%p+sum[rs(x)]%p;
   sum[x]%=p;
} 

void build(int l,int r,int x){
   if(l==r){
   	sum[x]=w[l]%p;
   	sum[x]%=p;
   	lpos[x]=rpos[x]=l;
   	return ;
   }
   int mid=(l+r)>>1;
   build(l,mid,ls(x));
   build(mid+1,r,rs(x));
   lpos[x]=l;
   rpos[x]=r;
   up(x);
}
void down(int x){
   if(tag[x]){
   	tag[rs(x)]+=tag[x];
   	tag[ls(x)]+=tag[x];
   	tag[ls(x)]%=p;
   	tag[rs(x)]%=p;
   	sum[ls(x)]+=tag[x]%p*(rpos[ls(x)]-lpos[ls(x)]+1)%p;
   	sum[rs(x)]+=tag[x]%p*(rpos[rs(x)]-lpos[rs(x)]+1)%p;
   	sum[ls(x)]%=p;
   	sum[rs(x)]%=p;
   	tag[x]=0;
   }
}

void modify(int l,int r,int ql,int qr,int x,int val){
   if(l>=ql&&r<=qr){
   	sum[x]+=(r-l+1)%p*val%p;
   	sum[x]%=p;
   	tag[x]+=val%p;
   	tag[x]%=p;
   	return ;
   }
   down(x);
   int mid=(l+r)>>1;
   if(mid>=ql)
   	modify(l,mid,ql,qr,ls(x),val);
   if(mid<qr)
   	modify(mid+1,r,ql,qr,rs(x),val);
   up(x);
}

int query(int l,int r,int ql,int qr,int x){
   if(l>=ql&&r<=qr)
   	return sum[x]%p;
   down(x);
   int mid=(l+r)>>1;
   int ans=0;
   if(mid>=ql)
   	ans+=query(l,mid,ql,qr,ls(x));
   if(mid<qr)
   	ans+=query(mid+1,r,ql,qr,rs(x));
   return ans%p;
}
//从x-y链上所有节点加上z op==1
void modifychain(int x,int y,int z){
   z%=p;
   
   while(top[x]!=top[y]){
   	if(dep[top[x]]<dep[top[y]])
   		swap(x,y);
   	modify(1,n,dfn[top[x]],dfn[x],1,z);
   	x= fa[top[x]];
   }
   if(dep[x]>dep[y])
   	swap(x,y);
   modify(1,n,dfn[x],dfn[y],1,z);
   
} 
//从x到y结点最短路上所有结点的和 op==2
int querychain(int x,int y){
   int ans=0;
   while(top[x]!=top[y]){
   	if(dep[top[x]]<dep[top[y]])
   		swap(x,y);
   		ans+=query(1,n,dfn[top[x]],dfn[x],1);
   		ans%=p;
   		x = fa[top[x]]; 
   }
   if(dep[x]>dep[y])
   	swap(x,y);
   ans+=query(1,n,dfn[x],dfn[y],1);
   return ans%p;
}
//以x为根节点的子树所有节点加上z op==3 
void modifyson(int x,int z){
   modify(1,n,dfn[x],dfn[x]+siz[x]-1,1,z);
}

int queryson(int x){
   return query(1,n,dfn[x],dfn[x]+siz[x]-1,1)%p;
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   memset(head,0,sizeof(head));
   cin>>n>>m>>r>>p;
   for(int i=1;i<=n;++i){
   	cin>>v[i];
   }
   for(int i=1;i<n;++i){
   	int u,v;
   	cin>>u>>v;
   	add(u,v);
   	add(v,u);
   }
   dfs1(r,r);
   dfs2(r,r);
   build(1,n,1);
   for(int i=1;i<=m;++i){
   	int op;
   	cin>>op;
   	if(op==1){
   		int x,y,z;
   		cin>>x>>y>>z;
   		modifychain(x,y,z);
   	}
   	else if(op==2){
   		int x,y;
   		cin>>x>>y;
   		cout<<querychain(x,y)%p<<'\n';
   	}
   	else if(op==3){
   		int x,z;
   		cin>>x>>z;
   		modifyson(x,z);
   	}
   	else if(op==4){
   		int x;
   		cin>>x;
   		cout<<queryson(x)%p<<'\n';
   	}
   }
   return 0;
}

O - 最短距离

#include <bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=1e5+10;
int n,m;
struct edge{
   int v,w,nxt;
}e[N<<2];
int dep[N],son[N];
int top[N],siz[N];
int fa[N];
int gu,gv,gw;
ll tr[N<<2];
int cnt,tim;
int dfn[N];
int b[N];
int head[N<<1];
int fr[N],to[N],val[N];
void add(int u,int v,int w){
   e[++cnt].v=v;
   e[cnt].w=w;
   e[cnt].nxt=head[u];
   head[u]=cnt;
}
int f[N];
int find(int x){
   if(f[x]==x) return x;
   return f[x]=find(f[x]);
}
void dfs1(int u,int f){
   fa[u]=f;
   dep[u]=dep[f]+1;
   siz[u]=1;
   int mm=-1;
   for(int i=head[u];i;i=e[i].nxt){
   	int v=e[i].v;
   	if(v==f) continue;
   	dfs1(v,u);
   	siz[u]+=siz[v];
   	if(siz[v]>mm){
   		mm=siz[v];
   		son[u]=v;
   	}
   }
}

void dfs2(int u,int f){
   top[u]=f;
   dfn[u]=++tim;
   if(son[u]) 
   	dfs2(son[u],f);
   for(int i=head[u];i;i=e[i].nxt){
   	int v=e[i].v;
//		if(v==fa[u]||v==son[u])
//			continue;
//		else
//			dfs2(v,v);
//		if(v!=fa[u])
//			b[dfn[v]]=e[i].w;
   	if(v != fa[u])
   	{
   		if(v != son[u])dfs2(v, v);
   		b[dfn[v]] =e[i].w;
   	}
   }
}
ll ls(ll x){
   return x<<1;
}
ll rs(ll x){
   return x<<1|1;
}
void up(int x){
   tr[x]=tr[ls(x)]+tr[rs(x)];
}
void build(int l,int r,int x){
   if(l==r){
   	tr[x]=b[l];
   	return ;
   }
   int mid=(l+r)>>1;
   build(l,mid,ls(x));
   build(mid+1,r,rs(x));
   up(x);
}
void update(int l,int r,int p,int y,int x){
   if(l==r){
   	tr[x]=y;
   	return ;
   }
   int mid=(l+r)>>1;
   if(mid>=p)
   	update(l,mid,p,y,ls(x));
   else
   	update(mid+1,r,p,y,rs(x));
   up(x);
}
ll query(int l,int r,int ql,int qr,int x){
   ll ans=0;
   if(ql>qr) return 0;
   if(l==ql&&r==qr)
   	return tr[x];
   int mid=(l+r)>>1;
//	if(mid>=ql)
//		ans+=query(l,mid,ql,qr,ls(x));
//	if(mid<qr)
//		ans+=query(mid+1,r,ql,qr,rs(x));
//	return ans;
   if(qr <= mid)return query(l, mid, ql, qr, ls(x));
   else if(ql > mid)return query(mid+1, r, ql, qr, rs(x));
   else return query(l, mid, ql, mid, ls(x))+
   			query(mid+1, r, mid+1, qr, rs(x));

}
//求树上u到v的距离 
ll solve(int u,int v){
   ll ans=0;
   while(top[u]!=top[v]){
//		if(dep[top[u]]<dep[top[v]])
//			swap(u,v);
//		ans+=query(1,n,dfn[top[u]],dfn[u],1);
//		u = fa[top[u]];
   	if(dep[top[u]] > dep[top[v]])
   	{
   		ans += query(1, n, dfn[top[u]], dfn[u], 1);
   		u = fa[top[u]];
   	}
   	else
   	{
   		ans += query(1, n, dfn[top[v]], dfn[v], 1);
   		v = fa[top[v]];
   	}

   }
//	if(dep[u]>dep[v])
//		swap(u,v);
//	ans+=query(1,n,dfn[u]+1,dfn[v],1);
   if(dep[u] < dep[v])
   	ans += query(1, n, dfn[u]+1, dfn[v], 1);
   else 
   	ans += query(1, n, dfn[v]+1, dfn[u], 1);
   return ans;
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n>>m;
   for(int i=1;i<=n;++i){
   	f[i]=i;
   }
   for(int i=1;i<=n;++i){
   	int u,v,w;
   	cin>>u>>v>>w;
   	fr[i]=u;
   	to[i]=v;
   	val[i]=w;
   	int x=find(u);
   	int y=find(v);
   	if(x==y){
   		gu=u;
   		gv=v;
   		gw=w;
   	} 
   	else{
   		f[x]=y;
   		add(u,v,w);
   		add(v,u,w);
   	}
   }
   dfs1(1,1);
   b[dfn[1]]=0;
   dfs2(1,1);
   build(1,n,1);
   while(m--){
   	int op,x,y;
   	cin>>op>>x>>y;
   	if(op==1){
   		if(gu==fr[x]&&gv==to[x]){
   			gw=y;
   		}
   		else if(dep[fr[x]]>dep[to[x]]){
   				update(1,n,dfn[fr[x]],y,1);
   		}
   		else{
   			update(1,n,dfn[to[x]],y,1);
   		}
   	
   	}
   	else{
   		ll ans=solve(x,y);
   		ans=min({ans,gw+solve(x,gu)+solve(y,gv),gw+solve(x,gv)+solve(y,gu)});
   		cout<<ans<<'\n';
   	}
   }
   
   
   return 0;
}

P - Minimum spanning tree for each edge

#include <bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=2e5+10;
struct edge{
   ll u,v,w;
}e[N],d[N];
ll f[N],val[N];
ll dep[N],fa[N],siz[N],top[N],son[N],rev[N];
struct tree{
   ll l,r,sum;
}tr[N<<2];
ll n,m;

ll dfn[N];
ll tot=1;
vector < pair <ll,ll> > g[N];
ll find(ll x){
   if(f[x]==x) return x;
   return f[x]=find(f[x]);
}
bool cmp(edge a,edge b){
   return a.w<b.w;
}
ll res;
void dfs1(ll u,ll f){
   dep[u]=dep[f]+1;
   fa[u]=f;
   siz[u]=1;
   int len=g[u].size();
   for(int i=0;i<len;++i){
   	ll v=g[u][i].first;
   	if(v==f) continue;
   	val[v]=g[u][i].second;
   	dfs1(v,u);
   	siz[u] += siz[v];
   	if(siz[v]>siz[son[u]])
   		son[u]=v;
   }
}
void dfs2(ll u,ll f){
   if(!son[u]) return ;
   top[son[u]]= top[u];
   dfn[son[u]]= ++tot;
   rev[tot]=son[u];
   dfs2(son[u],u);
   int len=g[u].size();
   for(int i=0;i<len;++i){
   	ll v=g[u][i].first;
   	if(v==f||v==son[u]) continue;
   	top[v]=v;
   	dfn[v]= ++tot;
   	rev[tot]=v;
   	dfs2(v,u);
   }
}
ll ls(ll x){
   return x<<1;
}
ll rs(ll x){
   return x<<1|1;
}
void build(ll l,ll r,ll x){
   tr[x].l=l;
   tr[x].r=r;
   if(l==r){
   	tr[x].sum=val[rev[l]];
   	return ;
   } 
   ll mid=(l+r)>>1;
   build(l,mid,ls(x));
   build(mid+1,r,rs(x));
   tr[x].sum=max(tr[ls(x)].sum,tr[rs(x)].sum);
}
ll query(ll ql,ll qr,ll x){
   if(ql>qr) return 0;
   if(tr[x].l>=ql&&tr[x].r<=qr)
   	return tr[x].sum;
   ll ans=0;
   ll mid=(tr[x].l+tr[x].r)>>1;
   if(mid>=ql)
   	ans=max(ans,query(ql,qr,ls(x)));
   if(mid<qr)
   	ans=max(ans,query(ql,qr,rs(x)));
   return ans;
}
ll qrange(ll x,ll y){
   ll ans=0;
   while(top[x]!=top[y]){
   	if(dep[top[x]]<dep[top[y]])
   		swap(x,y);
   	ans=max(ans,query(dfn[top[x]],dfn[x],1));
   	x=fa[top[x]];
   	if(x==0) x=1;
   }
   if(dep[x]>dep[y])
   	swap(x,y);
   ans=max(ans,query(dfn[son[x]],dfn[y],1));
   return ans;
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n>>m;
   for(int i=1;i<=m;++i){
   	cin>>e[i].u>>e[i].v>>e[i].w;
   	d[i]=e[i];
   }
   for(int i=1;i<=n;++i){
   	f[i]=i;
   }
   sort(e+1,e+1+m,cmp);
   for(int i=1;i<=m;++i){
   	ll x=find(e[i].u);
   	ll y=find(e[i].v);
   	if(x==y) continue;
   	f[x]=y;
   	g[e[i].u].push_back({e[i].v,e[i].w});
   	g[e[i].v].push_back({e[i].u,e[i].w});
   	res+=e[i].w;
   }
   dfs1(1,0);
   top[1]=dfn[1]=rev[1]=1;
   dfs2(1,0);
   build(1,n,1);
   for(int i=1;i<=m;++i){
   	cout<<res+d[i].w-qrange(d[i].u,d[i].v)<<'\n';
   }
   return 0;
}

训练19

H - 小白逛公园

#include <bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=5e5+10;
struct tree{
   int l,r;
   ll maxleft,maxright,ans,sum;
}tr[N<<2];
int n,m;
int ls(int x){
   return x<<1;
}
int rs(int x){
   return x<<1|1;
}
void up(int x){
   tr[x].sum=tr[ls(x)].sum+tr[rs(x)].sum;
   tr[x].maxleft=max(tr[ls(x)].maxleft,tr[ls(x)].sum+tr[rs(x)].maxleft);
   tr[x].maxright=max(tr[rs(x)].maxright,tr[ls(x)].maxright+tr[rs(x)].sum);
   tr[x].ans=max({tr[ls(x)].ans,tr[rs(x)].ans,tr[ls(x)].maxright+tr[rs(x)].maxleft});
}
void build(int l,int r,int x){
   tr[x].l=l;
   tr[x].r=r;
   if(l==r){
   	cin>>tr[x].sum;
   	tr[x].maxleft=tr[x].maxright=tr[x].ans=tr[x].sum;
   	return ;
   }
   int mid=(l+r)>>1;
   build(l,mid,ls(x));
   build(mid+1,r,rs(x));
   up(x);
}
tree query(int ql,int qr,int x){
   if(tr[x].l>=ql&&tr[x].r<=qr){
   	return tr[x];
   }
   int mid=(tr[x].l+tr[x].r)>>1;
   if(mid>=qr)
   	return query(ql,qr,ls(x));
   else{
   	if(mid<ql)
   		return query(ql,qr,rs(x));
   	else{
   		tree t,a,b;
   		a=query(ql,qr,ls(x));
   		b=query(ql,qr,rs(x));
   		t.maxleft=max(a.maxleft,a.sum+b.maxleft);
   		t.maxright=max(b.maxright,b.sum+a.maxright);
   		t.ans=max({a.ans,b.ans,a.maxright+b.maxleft});
   		return t;
   	}
   } 
}
void change(int p,int s,int x){
   if(tr[x].l==tr[x].r){
   	tr[x].maxleft=tr[x].maxright=tr[x].ans=tr[x].sum=s;
   	return ;
   }
   int mid=(tr[x].l+tr[x].r)>>1;
   if(mid>=p) change(p,s,ls(x));
   else change(p,s,rs(x));
   up(x);
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n>>m;
   build(1,n,1);
   while(m--){
   	int op,x,y;
   	cin>>op>>x>>y;
   	if(op==1){
   		if(x>y) swap(x,y);
   		cout<<query(x,y,1).ans<<'\n';
   	}
   	else{
   		change(x,y,1);
   	}
   }
   return 0;
}

K - The Child and Sequence

#include <bits/stdc++.h>
#define int long long 
using namespace std;
const int N=1e5+10;
int n,m,a[N];
int t[N<<2];
int tr[N<<2];
int ls(int x){
	return x<<1;
}
int rs(int x){
	return x<<1|1;
}

void up(int x){
	tr[x]=max(tr[ls(x)],tr[rs(x)]);
	t[x]=t[ls(x)]+t[rs(x)];
}
void build(int l,int r,int x){
	if(l==r){
		t[x]=tr[x]=a[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls(x));
	build(mid+1,r,rs(x));
	up(x);
	
}
void modify(int x,int l,int r,int pos,int val){
	if(l==r){
		t[x]=tr[x]=val;
		return ;
	}
	int mid=(l+r)>>1;
	if(mid>=pos)
		modify(ls(x),l,mid,pos,val);
	else 
		modify(rs(x),mid+1,r,pos,val);
	up(x); 
}
void mod(int x,int l,int r,int ql,int qr,int p){
	if(tr[x]<p) return ;
	if(l==r){
		t[x]%=p;
		tr[x]%=p;
		return ;
	}
	int mid=(l+r)>>1;
	if(mid>=ql) mod(ls(x),l,mid,ql,qr,p);
	if(qr>mid) mod(rs(x),mid+1,r,ql,qr,p);
	up(x);
}
int query(int x,int l,int r,int ql,int qr){
	if(l>=ql&&r<=qr){
		return t[x];
	}
	int mid=(l+r)>>1;
	int ans=0;
	if(mid>=ql) ans+=query(ls(x),l,mid,ql,qr);
	if(qr>mid) ans+=query(rs(x),mid+1,r,ql,qr);
	return ans; 
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;++i){
		cin>>a[i];
	}
	build(1,n,1);
	while(m--){
		int op,x,y;
		cin>>op>>x>>y;
		if(op==1){
			cout<<query(1,1,n,x,y)<<'\n';
		}
		else if(op==2){
			int z;
			cin>>z;
			mod(1,1,n,x,y,z);
		}
		else{
			modify(1,1,n,x,y);
		}
	}
	return 0;
}

L - Subarray Sorting

#include <bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=3e5+10;
int n;
int a[N];
int b[N];
int pos[N];
int tr[N<<2];
int cnt[N];
queue <int> q[N];
ll ls(ll x){
   return x<<1;
}
ll rs(ll x){
   return x<<1|1;
}
void up(int x){
   tr[x]=min(tr[ls(x)],tr[rs(x)]);
}
void build(int l,int r,int x){
   if(l==r){
   	tr[x]=a[l];
   	return ;
   }
   int mid=(l+r)>>1;
   build(l,mid,ls(x));
   build(mid+1,r,rs(x));
   up(x);
}
void modify(int l,int r,int x,int pos){
   if(l==r){
   	tr[x]=0x3f3f3f3f;
   	return ;
   }
   int mid=(l+r)>>1;
   if(mid>=pos) modify(l,mid,ls(x),pos);
   else modify(mid+1,r,rs(x),pos);
   up(x);
}
int query(int l,int r,int x,int ql,int qr){
   if(l>=ql&&r<=qr){
   	return tr[x];
   }
   int mid=(l+r)>>1;
   if(mid>=ql&&mid<qr)
   	return min(query(l,mid,ls(x),ql,qr),query(mid+1,r,rs(x),ql,qr));
   if(mid>=ql)
   	return query(l,mid,ls(x),ql,qr);
   return query(mid+1,r,rs(x),ql,qr);
}
void solve(){
   cin>>n;
   for(int i=1;i<=n;++i){
   	cnt[i]=0;
   }
   for(int i=1;i<=n;++i){
   	cin>>a[i];
   	cnt[a[i]]++;
   }
   for(int i=1;i<=n;++i){
   	cin>>b[i];
   	cnt[b[i]]--;
   }
   bool flag=1;
   for(int i=1;i<=n;++i){
   	if(cnt[i]){
   		cout<<"NO\n";
   		return ;
   	}
   }
   for(int i=1;i<=n;++i){
   	q[a[i]].push(i);
   }
   for(int i=1;i<=n;++i){
   	pos[i]=q[b[i]].front();
   	q[b[i]].pop();
   }
   build(1,n,1);
   for(int i=1;i<=n;++i){
   	if(query(1,n,1,1,pos[i])!=b[i]){
   		flag=0;
   		break;
   	}
   	modify(1,n,1,pos[i]);
   }
   if(flag) cout<<"YES\n";
   else cout<<"NO\n";	
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   int t;
   cin>>t;
   while(t--){
   	solve();
   }
   
   return 0;
}

M - Sereja and Brackets

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
struct tree{
   int lsum,rsum;
}tr[N<<2];
char s[N];
int n,m;
int ls(int x){
   return x<<1;
}
int rs(int x){
   return x<<1|1;
}
void up(int x){
   tr[x].lsum=tr[ls(x)].lsum+tr[rs(x)].lsum-min(tr[ls(x)].lsum,tr[rs(x)].rsum);
   tr[x].rsum=tr[ls(x)].rsum+tr[rs(x)].rsum-min(tr[ls(x)].lsum,tr[rs(x)].rsum);
}

void build(int l,int r,int x){
   if(l==r){
   	if(s[l]=='(')
   		tr[x].lsum=1;
   	if(s[l]==')')
   		tr[x].rsum=1;
   	return ;
   }
   int mid=(l+r)>>1;
   build(l,mid,ls(x));
   build(mid+1,r,rs(x));
   up(x);
}
tree query(int l,int r,int x,int ql,int qr){
   if(l>=ql&&r<=qr){
   	return tr[x];
   }
   int mid=(l+r)>>1;
   if(mid>=qr) 
   	return query(l,mid,ls(x),ql,qr);
   if(mid<ql) 

   	return query(mid+1,r,rs(x),ql,qr);
   tree a=query(l,mid,ls(x),ql,qr);
   tree b=query(mid+1,r,rs(x),ql,qr);
   tree ans;
   ans.lsum=a.lsum+b.lsum-min(a.lsum,b.rsum);
   ans.rsum=a.rsum+b.rsum-min(a.lsum,b.rsum);
   return ans;
   	
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>s+1;
   n=strlen(s+1);
   build(1,n,1);
   cin>>m;
   while(m--){
   	 int l,r;
   	 cin>>l>>r;
   	 tree ans=query(1,n,1,l,r);
   	 cout<<(r-l+1)-ans.lsum-ans.rsum<<'\n';
   }
   
   
   
   return 0;
}

S - Closest Equals

#include <bits/stdc++.h>
using namespace std;
const int N=2e6+10;
const int inf=0x3f3f3f3f;
struct que{
   int l,r,id;
}q[N];
bool cmp(que a,que b){
   return a.r<b.r;
}
int b[N],ans[N];
int n,m;
int tr[N];
map <int,int> mp;
int ls(int x){
   return x<<1;
}
int rs(int x){
   return x<<1|1;
}

void update(int x,int l,int r,int u,int val){
   if(l==r&&l==u){
   	tr[x]=val;
   	return ;
   }
   if(l>u||r<u) return ;
   int mid=(l+r)>>1;
   update(ls(x),l,mid,u,val);
   update(rs(x),mid+1,r,u,val);
   tr[x]=min(tr[ls(x)],tr[rs(x)]);
}
int query(int x,int l,int r,int ql,int qr){
   if(l>=ql&&r<=qr){
   	return tr[x];
   }
   if(l>qr||r<ql) return inf;
   int mid=(l+r)>>1;
   int a=query(ls(x),l,mid,ql,qr);
   int b=query(rs(x),mid+1,r,ql,qr);
   int ans=min(a,b);
   return ans;
}
int main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
   cin>>n>>m;
   for(int i=1;i<4*n;++i){
   	tr[i]=inf;
   }
   for(int i=1;i<=n;++i){
   	cin>>b[i];
   }
   for(int i=1;i<=m;++i){
   	cin>>q[i].l>>q[i].r;
   	q[i].id=i;
   }
   sort(q+1,q+1+m,cmp);
   int tot=1;
   for(int i=1;i<=n;++i){
   	if(mp[b[i]])
   		update(1,1,n,mp[b[i]],i-mp[b[i]]);
   	while(tot<=m&&i==q[tot].r){
   		ans[q[tot].id]=query(1,1,n,q[tot].l,q[tot].r);
   		tot++;
   	}
   	mp[b[i]]=i;	
   }
   for(int i=1;i<=m;++i){
   	if(ans[i]==inf) cout<<-1<<'\n';
   	else cout<<ans[i]<<'\n'; 
   }
   return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值