寒假集训记录


集训:

贪心与二分:

P1020 [NOIP1999 普及组] 导弹拦截

之前求最长上升子序列都是用(O(n^2))做的,现在发现(O(nlogn))做法的妙处了!同时复习了一下二分,收获很多的一道题

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 50007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,k,ans1,ans2;
int a[N],mx[N];
bool Solve()
{
 	//freopen("test.in","r",stdin);
 	int in;
	while(scanf("%lld",&in)!=EOF)
		a[++n]=in;
	mx[0]=inf;
	for(int i=1;i<=n;++i)
	{
		int l=0,r=ans1+1,mid;
		while(l<r-1)
		{
			mid=l+((r-l)>>1);
			if(mx[mid]>=a[i])
				l=mid;
			else
				r=mid;
		}
		ans1=max(ans1,l+1);
		mx[l+1]=a[i];
	}
	memset(mx,0,sizeof(mx));
	for(int i=1;i<=n;++i)
	{
		int l=0,r=ans2+1,mid;
		while(l<r-1)
		{
			mid=l+((r-l)>>1);
			if(mx[mid]<a[i])
				l=mid;
			else
				r=mid;
		}
		ans2=max(ans2,l+1);
		mx[l+1]=a[i];
	}
	printf("%lldn%lld",ans1,ans2);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/

P1080 [NOIP2012 提高组] 国王游戏

先手推乱搞出大臣的排队顺序,然后发现要高精。。。于是去题解里面搬了个板子美滋滋~

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1007
#define M 10007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Node
{
	int l,r;
}a[N];
int T=1,n;
void H_cpy(int *num1,int *num2)
{
	for(int i=0;i<M;++i) num1[i]=num2[i];
}
bool H_cmp(int *num1,int *num2)
{
	for(int i=M-1;i>=0;--i)
	{
		if(num1[i]>num2[i]) return 1;
		if(num1[i]<num2[i]) return 0;
	}
	return 0;
}
void H_time(int *num1,int val)
{
	for(int i=M-2;i>=0;--i) num1[i]*=val;
	for(int i=0;i<M-1;++i)
	{
		num1[i+1]+=(num1[i]/10);
		num1[i]%=10;
	}
}
void H_div(int *num1,int *num2,int val)
{
	memset(num2,0,sizeof(num2));
	int x=0;
	for(int i=M-1;i>=0;--i)
	{
    	x=x*10+num1[i];
		num2[i]=x/val;
		x%=val;
	}
}
void H_print(int *num1)
{
	bool flag=0;
	for(int i=M-1;i>=0;--i)
	{
		if(!flag)
		{
			if(num1[i]) flag=1;
			else continue;
		}
		printf("%d",num1[i]);
	}
}
bool Cmp(Node x,Node y)
{
	return x.l*x.r<y.l*y.r;
}
int ans[M],now[M],tmp[M];
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=0;i<=n;++i)
		scanf("%lld%lld",&a[i].l,&a[i].r);
	sort(a+1,a+1+n,Cmp);
	now[0]=1;
	H_time(now,a[0].l);
	for(int i=1;i<=n;++i)
	{
		H_div(now,tmp,a[i].r);
		if(H_cmp(tmp,ans))
			H_cpy(ans,tmp);
		H_time(now,a[i].l);
	}
	H_print(ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/

P1209 [USACO1.3]修理牛棚 Barn Repair

细节没把握好导致多(WA)了几遍,思路很简单的一道题

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,k;
int a[N],b[N];
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i=1;i<=k;++i)
		scanf("%lld",&a[i]);
	sort(a+1,a+1+k);
	for(int i=1;i<=k;++i)
		b[i]=a[i]-a[i-1]-1;
	sort(b+2,b+1+k);
	int ans=a[k]-a[1]+1;
	for(int i=1;i<n;++i)
	{
		if(k-i+1==1)
			break;
		ans-=b[k-i+1];
	}
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/

P2123 皇后游戏

我真的不配(AC)这道题,感谢 >  【大佬的博客】   给我的方法以及对相关问题的思考,目前理解的还不深,每天会来啃一啃。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 20007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Node
{
	int l,r;
}a[N];
int T=1,n,m,k;
bool Cmp(Node x,Node y)
{
	if(min(x.l,y.r)==min(x.r,y.l))
		return x.l<y.l;
	return min(x.l,y.r)<min(x.r,y.l);
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
 	scanf("%lld",&n);
 	for(int i=1;i<=n;++i)
 		scanf("%lld%lld",&a[i].l,&a[i].r);
 	sort(a+1,a+1+n,Cmp);
 	int ans=a[1].l+a[1].r,now=a[1].l+a[1].r,sum=a[1].l;
 	for(int i=2;i<=n;++i)
 	{
 		sum+=a[i].l;
		now=max(now,sum)+a[i].r; 
		ans=max(ans,now);
	}
	printf("%lldn",ans);
	return true;
}
signed main()
{
	scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/

「RdOI R2」称重(weigh)

好久没写交互题了,一写就是一坨屎山,交了半天交过去了,但是不知道为啥我之前写二分写第五个点会(WA),不想太看屎山了,就这样吧(qwq)

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,cnt,ans[2];
void Judge(int l,int r,int now)
{
	int n=r-l+1;
	if(n&1)
	{
		if(now==2)
		{
			printf("1 %lld ",n/2);
			for(int i=1;i<=n/2;++i)
				printf("%lld ",l+i-1);
			printf("%lld ",n/2);
			for(int i=n/2+1;i<n;++i)
				printf("%lld ",l+i-1);	
			printf("n");
			char in;
			cin>>in;
			if(in=='=')
			{
				if(n==3)
				{
					ans[++cnt]=l;
					ans[++cnt]=l+1;
					return;
				}
				Judge(l,l+n/2-1,1);
				Judge(l+n/2,l+n-1,1);
				return;
			}
			if(in=='<')
			{
				if(n==3)
				{
					ans[++cnt]=l;
					ans[++cnt]=r;
					return;
				}
				printf("1 1 %lld 1 %lldn",r-1,r);
				char in1;
				cin>>in1;
				if(in1=='=')
					Judge(l,l+n/2-1,2);
				if(in1=='>')
				{
					ans[++cnt]=r;
					Judge(l,l+n/2-1,1);
				}
				return;
			}
			if(in=='>')
			{
				if(n==3)
				{
					ans[++cnt]=l+1;
					ans[++cnt]=r;
					return;
				}
				printf("1 1 %lld 1 %lldn",l,r);
				char in1;
				cin>>in1;
				if(in1=='=')
					Judge(l+n/2,l+n-1,2);
				if(in1=='>')
				{
					ans[++cnt]=r;
					Judge(l+n/2,l+n-1,1);
				}
				return;
			}
		}
		else
		{
			printf("1 %lld ",n/3);
			for(int i=1;i<=n/3;++i)
				printf("%lld ",l+i-1);
			printf("%lld ",n/3);
			for(int i=n/3+1;i<=n/3*2;++i)
				printf("%lld ",l+i-1);	
			printf("n");
			char in;
			cin>>in;
			if(in=='=')
			{
				if(n==3)
				{
					ans[++cnt]=r;
					return;
				}
				Judge(l+n/3*2,r,1);
				return;
			}
			if(in=='<')
			{
				if(n==3||n==4||n==5)
				{
					ans[++cnt]=l;
					return;
				}
				Judge(l,l+n/3-1,1);
				return;
			}
			if(in=='>')
			{
				if(n==3||n==4||n==5)
				{
					ans[++cnt]=l+1;
					return;
				}
				Judge(l+n/3,l+n/3*2-1,1);
				return;
			}
		}
	}
	else
	{
		if(now==2)
		{
			printf("1 %lld ",n/2);
			for(int i=1;i<=n/2;++i)
				printf("%lld ",l+i-1);
			printf("%lld ",n/2);
			for(int i=n/2+1;i<=n;++i)
				printf("%lld ",l+i-1);	
			printf("n");
			char in;
			cin>>in;
			if(in=='=')
			{
				if(n==2)
				{
					ans[++cnt]=l,ans[++cnt]=r;
					return;
				}
				Judge(l,l+n/2-1,1);
				Judge(l+n/2,l+n-1,1);
				return;
			}
			if(in=='<')
			{
				Judge(l,l+n/2-1,2);
				return;
			}
			if(in=='>')
			{
				Judge(l+n/2,l+n-1,2);
				return;
			}
		}
		else
		{
			if(n==2)
			{
				printf("1 %lld ",n/2);
				for(int i=1;i<=n/2;++i)
					printf("%lld ",l+i-1);
				printf("%lld ",n/2);
				for(int i=n/2+1;i<=n;++i)
					printf("%lld ",l+i-1);	
				printf("n");
				char in;
				cin>>in;
				if(in=='<')
					ans[++cnt]=l;
				else
					ans[++cnt]=r;
				return; 
			}
			printf("1 %lld ",n/3);
			for(int i=1;i<=n/3;++i)
				printf("%lld ",l+i-1);
			printf("%lld ",n/3);
			for(int i=n/3+1;i<=n/3*2;++i)
				printf("%lld ",l+i-1);	
			printf("n");
			char in;
			cin>>in;
			if(in=='=')
			{
				if(n==3)
				{
					ans[++cnt]=r;
					return;
				}
				Judge(l+n/3*2,r,1);
				return;
			}
			if(in=='<')
			{
				if(n==3||n==4||n==5)
				{
					ans[++cnt]=l;
					return;
				}
				Judge(l,l+n/3-1,1);
				return;
			}
			if(in=='>')
			{
				if(n==3||n==4||n==5)
				{
					ans[++cnt]=l+1;
					return;
				}
				Judge(l+n/3,l+n/3*2-1,1);
				return;
			}
		}
	} 

}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	Judge(1,n,2);
	printf("2 %lld %lldn",min(ans[1],ans[2]),max(ans[1],ans[2]));
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/

KMP与Trie:

P4824 [USACO15FEB] Censoring S

考察对(Kmp)的魔改的一个题,用栈来模拟删除操作

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 0x3f3f3f3f
#define inc 0xcfcfcfcf
#define N 1000007
#define mod 1000000007
using namespace std;
int T=1,n,m,k,cnt;
int a[N],fail[N];
int stk[N],pos[N];
void Kmp(string t,string p)
{
	int lt=t.size(),lp=p.size();
	int j=0;
	for(int i=1;i<lp;i++)//fail指针 
	{
		j=fail[i];
		while(j&&p[i]!=p[j])
			j=fail[j];
		if(p[i]==p[j])
			fail[i+1]=j+1;
		else
			fail[i+1]=0;
	}
	j=0;
	for(int i=0;i<lt;i++)
	{
		while(j&&t[i]!=p[j])
			j=fail[j];
		if(t[i]==p[j])
			j++;
		pos[i]=j;
		stk[++cnt]=i;
		if(j==lp)
		{
			cnt-=lp;
			j=pos[stk[cnt]];
		}
	}
}

bool Solve()
{
	string in1,in2;
	cin>>in1>>in2;
	Kmp(in1,in2);	
	for(int i=1;i<=cnt;++i)
		printf("%c",in1[stk[i]]);
	return true;
}
signed main()
{
	scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/

Compress Words

改了半天终于改对了

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n;
int fail[N*10];
string a[N];
int Get_fail(string p)
{
	//memset(fail,0,sizeof(fail));
	int lp=p.size();
	int j=0;
	for(int i=1;i<lp;i++)
	{
		j=fail[i];
		while(j&&p[i]!=p[j])
			j=fail[j];
		if(p[i]==p[j])
			fail[i+1]=j+1;
		else
			fail[i+1]=0;
	}
	return fail[lp];
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
		cin>>a[i];
	string ans=a[1];
	for(int i=2;i<=n;++i)
	{
		string x,y,z;
		int len1=ans.size(),len2=a[i].size();
		if(len1>=len2)
		{
			for(int j=len1-len2;j<len1;++j)
				x+=ans[j];
			y=a[i];
			z=y+"@"+x;
			int now=Get_fail(z);
			for(int j=now;j<len2;++j)
				ans+=a[i][j];
		}
		else
		{
			x=ans;
			for(int j=0;j<len1;++j)
				y+=a[i][j];
			z=y+"@"+x;
			int now=Get_fail(z);
			for(int j=now;j<len2;++j)
				ans+=a[i][j];
		}
	}
	cout<<ans<<endl;
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*

*/

P3435 [POI2006] OKR-Periods of Words

将前缀重复一次,变成当前子串最长公共前后缀问题,用fail指针求解

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 0x3f3f3f3f
#define inc 0xcfcfcfcf
#define N 1000007
#define mod 1000000007
using namespace std;
int T=1,n,m,k;
int a[N],fail[N];
void Kmp(string p)
{
	int lp=p.size();
	int j=0;
	for(int i=1;i<lp;i++)//fail指针 
	{
		j=fail[i];
		while(j&&p[i]!=p[j])
			j=fail[j];
		if(p[i]==p[j])
			fail[i+1]=j+1;
		else
			fail[i+1]=0;
	}
}

bool Solve()
{
	scanf("%lld",&n);
	string in;
	cin>>in;
	Kmp(in);	
	int ans=0;
	/*for(int i=1;i<=n;++i)
	{
		
		printf("%lld ",fail[i]);
	}*/
	for(int i=1;i<=n;++i)
	{
		int now=i;
		while(fail[now]) now=fail[now];
		if(fail[i])
			fail[i]=now;
		ans+=i-now;
	}
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/

P5410 【模板】扩展 KMP(Z 函数)

之前没学,离谱的是不吸氧过不了板子题,大概是string的功劳吧~~

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 0x3f3f3f3f
#define inc 0xcfcfcfcf
#define N 20000007
#define mod 1000000007
using namespace std;
int T=1,n,m,k;
int etd[N],nxt[N];
void Get_nxt(string s)//nxt[i]表示以s[i]开头的后缀与整串的lcp 
{
	int len=s.size();
	int pos=0,k=1,l;//k为 i+nxt[i]-1最大的那个i 
	nxt[0]=len;
	while(pos+1<len&&s[pos]==s[pos+1]) ++pos;
	nxt[1]=pos;
	for(int i=2;i<len;++i)
	{
		pos=k+nxt[k]-1;
		l=nxt[i-k];
		if(i+l<=pos)	nxt[i]=l;
		else
		{
			int j=max((int)0,pos-i+1);
			while(i+j<len&&s[i+j]==s[j]) ++j;
			nxt[i]=j;
			k=i; //刷新了最大值 
		}
	}
}
void Get_etd(string t,string p)
{
	int lt=t.size(),lp=p.size();
	int pos=0,k=0,l;
	while(pos<lt&&pos<lp&&t[pos]==p[pos])	++pos;
	etd[0]=pos;
	for(int i=1;i<lt;++i)
	{
		pos=k+etd[k]-1;
		l=nxt[i-k];
		if(i+l<=pos)	etd[i]=l;
		else
		{
			int j=max((int)0,pos-i+1);
			while(i+j<lt&&j<lp&&t[i+j]==p[j])	++j;
			etd[i]=j;
			k=i;
		}
	}
}
void Ex_kmp(string t,string p)
{
	Get_nxt(p);
	Get_etd(t,p); 
	int ans=nxt[0]+1;
	for(int i=1;i<p.size();++i)
		ans^=(i+1)*(nxt[i]+1);
	printf("%lldn",ans);
	ans=etd[0]+1;
	for(int i=1;i<t.size();++i)
		ans^=(i+1)*(etd[i]+1);
	printf("%lldn",ans);
}
bool Solve()
{
	string in1,in2;
	cin>>in1>>in2;
	Ex_kmp(in1,in2);	
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/

P2580 于是他错误的点名开始了

虽然可以直接map,但是太无聊了,这里给出另外两种水题法

法一:字符串哈希(虽然和map没两样

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 500007
#define mod 1000000007
#define K_1 19260817
#define K_2 1433223
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n;
int a[N];
map<int,int> mp1,mp2;
int Hash1(string s)
{
	int ans=0;
	for(int i=0;i<s.size();++i)
		ans=ans*K_1+s[i],ans%=mod;
	return ans;
}
int Hash2(string s)
{
	int ans=0;
	for(int i=0;i<s.size();++i)
		ans=ans*K_2+s[i],ans%=mod;
	return ans;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
	{
		string in;
		cin>>in;
		mp1.insert(make_pair(Hash1(in),1));
		mp2.insert(make_pair(Hash2(in),1));
	}
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
	{
		string in;
		cin>>in;
		int now1=Hash1(in),now2=Hash2(in);
		if(mp1[now1]==1&&mp2[now2]==1)
		{
			printf("OKn");
			++mp1[now1];
			++mp2[now2];
			continue;
		}
		if(mp1[now1]>1&&mp2[now2]>1)
		{
			printf("REPEATn");
			++mp1[now1];
			++mp2[now2];
			continue;
		}
		printf("WRONGn");
	}
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/


法二:字典树(常规方法吧属于是)

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Trie
{
	int ch[27],vis;
	bool is;
}tr[N];
int T=1,n,cnt;
void Insert(string s)
{
	int now=0;
	for(int i=0;i<s.size();++i)
	{
		int nxt=s[i]-'a';
		if(tr[now].ch[nxt])
			now=tr[now].ch[nxt];
		else
		{
			tr[now].ch[nxt]=++cnt;
			now=cnt; 
		}
	}
	tr[now].is=true;
}
int Search(string s)
{
	int now=0;
	for(int i=0;i<s.size();++i)
	{
		int nxt=s[i]-'a';
		if(tr[now].ch[nxt])
			now=tr[now].ch[nxt];
		else
			return 3;
	}
	if(tr[now].is)
	{
		if(!tr[now].vis)
		{
			++tr[now].vis;
			return 1;
		}
		else
			return 2;
	}
	else
		return 3;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
	{
		string in;
		cin>>in;
		Insert(in);
	}
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
	{
		string in;
		cin>>in;
		int opt=Search(in);
		if(opt==1)
			printf("OKn");
		if(opt==2)
			printf("REPEATn");
		if(opt==3)
			printf("WRONGn");
	}
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/


Prefixes and Suffixes

属实是好题,一开始求fail然后用kmp来求出现次数,本来是抱有侥幸心理看看能不能水过,果然第九个点T了,于是看题解发现用exkmp,但是我又不想改了,后面想想dp也能求出现次数,于是美美A掉

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,cnt;
int fail[N],ans[N],stk[N],f[N];
void Get_fail(string p)
{
	int lp=p.size();
	int j=0;
	for(int i=1;i<lp;i++)//fail指针 
	{
		j=ans[i];
		while(j&&p[i]!=p[j])
			j=ans[j];
		if(p[i]==p[j])
			ans[i+1]=j+1;
		else
			ans[i+1]=0;
	}
} 
bool Solve()
{
 	//freopen("test.in","r",stdin);
	string in;
	cin>>in;
	Get_fail(in);
	int now=in.size();
	while(now)
	{
		stk[++cnt]=now;
		now=ans[now];
	}
	for(int i=in.size();i;--i)
	{
		++f[i];
		f[ans[i]]+=f[i]; 
	}
	printf("%lldn",cnt);
	while(cnt)
		printf("%lld %lldn",stk[cnt],f[stk[cnt]]),--cnt;
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*
*/


P4551 最长异或路径

时隔三年已经忘记了异或问题可以用01Trie来做了,帮助回顾的好题,主要思路是求出每个点到任一点(这里统一为节点1)的路径异或和,并插入01字典树,然后由异或性质,每次定一个节点,寻找另一个节点使得两点异或和最大,往字典树相反方向走即可。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt,val;
}edge[N<<1];
struct Trie
{
	int ch[2];
}tr[N*10];
int T=1,n,ecnt,tcnt;
int head[N],dis[N];
void Add(int u,int v,int w)
{
	edge[++ecnt]=(Edge){v,head[u],w};
	head[u]=ecnt;
}
void Insert(int val)
{
	int now=0;
	int bts[40];
	for(int i=1;i<=34;++i)
	{
		bts[i]=val&1;
		val>>=1;
	}
	for(int i=34;i;--i)
	{
		if(tr[now].ch[bts[i]])
			now=tr[now].ch[bts[i]];
		else
		{
			tr[now].ch[bts[i]]=++tcnt;
			now=tcnt;
		}	
	}
}
void Dfs(int u,int fa,int val)
{
	int num=0;
	dis[u]=val;
	for(int i=head[u];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(v==fa)
			continue;
		++num;
		Dfs(v,u,val^edge[i].val);
	}
}
int Search(int val)
{
	int now=0;
	int bts[40];
	for(int i=1;i<=34;++i)
	{
		bts[i]=val&1;
		val>>=1;
	}
	for(int i=34;i;--i)
	{
		if(!bts[i])
		{
			if(tr[now].ch[1])
			{
				bts[i]=1;
				now=tr[now].ch[1];
			}
			else
				now=tr[now].ch[0];
		}
		else
		{
			if(tr[now].ch[0])
				now=tr[now].ch[0];
			else
			{
				bts[i]=0;
				now=tr[now].ch[1];
			}
		}
	}
	int ans=0;
	for(int i=34;i;--i)
		ans<<=1,ans+=bts[i];
	return ans;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<n;++i)
	{
		int u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		Add(u,v,w);
		Add(v,u,w);
	}
	Dfs(1,0,0);
	for(int i=1;i<=n;++i)
		Insert(dis[i]);
	int ans=0;
	for(int i=1;i<=n;++i)
		ans=max(ans,Search(dis[i]));
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/


P3879 [TJOI2010] 阅读理解

涨知识了,注释标记这行如果写成if(mp[j][in])最后一个点会MLE,好像原因是这样操作每次会新开一个点

点击查看代码
#include<bits/stdc++.h>
//#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m;
map<string,int> mp[N];
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		int num;
		string in;
		scanf("%d",&num);
		for(int j=1;j<=num;++j)
			cin>>in,mp[i][in]=1;
	}
	scanf("%d",&m);
	for(int i=1;i<=m;++i)
	{
		string in;
		cin>>in;
		for(int j=1;j<=n;++j)
			if(mp[j].count(in))//标记
				printf("%d ",j);
		printf("n");
	}
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/


![P7717 「EZEC-10」序列 ] 阅读理解 ](https://www.luogu.com.cn/problem/P7717)

这题可能理解的还不深,注释的地方改成31,32就WA了,之后再想想把

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 500007
#define M 37
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt,val;
}edge[N<<1];
struct Trie
{
	int ch[2];
}tr[N*100];
int T=1,n,m,k,ecnt,tcnt,ans=1;
int head[N],dis[N];
bool vis[N];
void Add(int u,int v,int w)
{
	edge[++ecnt]=(Edge){v,head[u],w};
	head[u]=ecnt;
}
void Insert(int val)
{
	int now=0;
	for(int i=30;i>=0;--i)//改成31,32就会错 
	{
		int nxt=(val>>i)&1;
		if(!tr[now].ch[nxt])
			tr[now].ch[nxt]=++tcnt;
		now=tr[now].ch[nxt];
	}
}
void Dfs(int u,int fa,int val)
{
	dis[u]=val;
	vis[u]=1;
	Insert(dis[u]);
	if(!ans)
		return;
	for(int i=head[u];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(v==fa)
			continue;
		if(vis[v])
		{
			if((val^edge[i].val)!=dis[v])
			{
				ans=0;
				return;
			}
			continue;
		}
		Dfs(v,u,val^edge[i].val);
	}
}
int Search(int now,int val,int pos)
{
	if(val>k)
		return 0;
	if(pos<0)
		return 1;
	if(tr[now].ch[0]&&tr[now].ch[1])
		return (Search(tr[now].ch[0],val+(1<<pos),pos-1)+Search(tr[now].ch[1],val+(1<<pos),pos-1))%mod;
	int nxt=max(tr[now].ch[0],tr[now].ch[1]);
	if((val+(1<<pos))<=k)
		return (Search(nxt,val+(1<<pos),pos-1)+(1<<pos))%mod;
	return  Search(nxt,val,pos-1)%mod;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i=1;i<=m;++i)
	{
		int u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		Add(u,v,w);
		Add(v,u,w);
	}
	for(int i=1;i<=n;++i)
	{
		if(vis[i])
			continue;
		Dfs(i,0,0);
		ans*=Search(0,0,30);//改成31,32就会错
		ans%=mod;
		if(!ans)
			break;
		for(int j=0;j<=tcnt;++j)
			tr[j].ch[0]=tr[j].ch[1]=0;
		tcnt=0;
	}
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/


树状数组与线段树

The Child and Sequence

经验太少了,这个题麻烦的就是取模操作,想着不能用标记实现,于是卡住

思路是区间取模时,搜索区间最大值,如果最大值小于要取模的数,就不需要继续下去,否则就暴力单点取模,维护最大值和区间和即可

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 500007
#define mod 1000000007
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
struct Tree
{
	int mx,sum;
}tr[N<<2];
int T=1,n,m,k;
int a[N];
void Pushup(int now)
{
	tr[now].mx=max(tr[now<<1].mx,tr[now<<1|1].mx);
	tr[now].sum=tr[now<<1].sum+tr[now<<1|1].sum;
}
void Build(int now,int l,int r)
{
	if(l==r)
	{
		tr[now].sum=a[l];
		tr[now].mx=a[l];
		return;
	}
	int mid=l+((r-l)>>1);
	Build(now<<1,l,mid);
	Build(now<<1|1,mid+1,r);
	Pushup(now); 
}
int Search_sum(int now,int l,int r,int ll,int rr)
{
	if(ll<=l&&r<=rr)
		return tr[now].sum;
	int mid=l+((r-l)>>1);
	if(rr<=mid)
		return Search_sum(now<<1,l,mid,ll,rr);
	if(ll>mid)
		return Search_sum(now<<1|1,mid+1,r,ll,rr);
	return Search_sum(now<<1,l,mid,ll,mid)+Search_sum(now<<1|1,mid+1,r,mid+1,rr);
}
void Update(int now,int l,int r,int pos,int val)
{
	if(l==pos&&l==r)
	{
		tr[now].mx=val;
		tr[now].sum=val;
		return;
	}
	int mid=l+((r-l)>>1);
	if(pos<=mid)
		Update(now<<1,l,mid,pos,val);
	else
		Update(now<<1|1,mid+1,r,pos,val);
	Pushup(now);
}
void Update_mod(int now,int l,int r,int ll,int rr,int val)
{
	if(ll<=l&&r<=rr)
	{
		if(tr[now].mx<val)
			return;
		if(l==r)
		{
			int tmp=tr[now].mx;
			tr[now].mx=tmp%val;
			tr[now].sum=tmp%val;
			return;
		}
	}
	int mid=l+((r-l)>>1);
	if(rr<=mid)
	{
		Update_mod(now<<1,l,mid,ll,rr,val);
		Pushup(now);
		return;
	}
	if(ll>mid)
	{
		Update_mod(now<<1|1,mid+1,r,ll,rr,val);
		Pushup(now);
		return;
	}
	Update_mod(now<<1,l,mid,ll,mid,val);
	Update_mod(now<<1|1,mid+1,r,mid+1,rr,val);
	Pushup(now);
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%lld",&a[i]);
	Build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		int opt,l,r,x;
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld%lld",&l,&r);
			printf("%lldn",Search_sum(1,1,n,l,r));
		}
		if(opt==2)
		{
			scanf("%lld%lld%lld",&l,&r,&x);
			Update_mod(1,1,n,l,r,x);
		}
		if(opt==3)
		{
			scanf("%lld%lld",&l,&x);
			Update(1,1,n,l,x);
		}
	}
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/


SUM and REPLACE

乐,以为上面这题暴力修改挺罕见的,没想到是一种套路化的了。。

这题思路是预处理出d[i],注意到d[1]=1,d[2]=2,因此如果一个区间全是1,2的话,就不用再修改了,于是套上面那题模板

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 1000007
#define mod 1000000007
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
struct Tree
{
	int mx,sum;
}tr[N<<2];
int T=1,n,m,k;
int a[N];
int d[M];
void Get_d()
{
	for(int i=1;i<=M-5;++i)
		for(int j=i;j<=M-5;j+=i)
			++d[j];
}
void Pushup(int now)
{
	tr[now].mx=max(tr[now<<1].mx,tr[now<<1|1].mx);
	tr[now].sum=tr[now<<1].sum+tr[now<<1|1].sum;
}
void Build(int now,int l,int r)
{
	if(l==r)
	{
		tr[now].sum=a[l];
		tr[now].mx=a[l];
		return;
	}
	int mid=l+((r-l)>>1);
	Build(now<<1,l,mid);
	Build(now<<1|1,mid+1,r);
	Pushup(now); 
}
int Search_sum(int now,int l,int r,int ll,int rr)
{
	if(ll<=l&&r<=rr)
		return tr[now].sum;
	int mid=l+((r-l)>>1);
	if(rr<=mid)
		return Search_sum(now<<1,l,mid,ll,rr);
	if(ll>mid)
		return Search_sum(now<<1|1,mid+1,r,ll,rr);
	return Search_sum(now<<1,l,mid,ll,mid)+Search_sum(now<<1|1,mid+1,r,mid+1,rr);
}
void Update_phi(int now,int l,int r,int ll,int rr)
{
	if(ll<=l&&r<=rr)
	{
		if(tr[now].mx<=2)
			return;
		if(l==r)
		{
			int tmp=tr[now].mx;
			tr[now].mx=d[tmp];
			tr[now].sum=d[tmp];
			return;
		}
	}
	int mid=l+((r-l)>>1);
	if(rr<=mid)
	{
		Update_phi(now<<1,l,mid,ll,rr);
		Pushup(now);
		return;
	}
	if(ll>mid)
	{
		Update_phi(now<<1|1,mid+1,r,ll,rr);
		Pushup(now);
		return;
	}
	Update_phi(now<<1,l,mid,ll,mid);
	Update_phi(now<<1|1,mid+1,r,mid+1,rr);
	Pushup(now);
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld",&n,&m);
	Get_d();
//	for(int i=1;i<=10;++i) 
//		printf("%lld:%lldn",i,d[i]);
	for(int i=1;i<=n;++i)
		scanf("%lld",&a[i]);
	Build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		int opt,l,r;
		scanf("%lld%lld%lld",&opt,&l,&r);
		if(opt==1)
			Update_phi(1,1,n,l,r);
		if(opt==2)
			printf("%lldn",Search_sum(1,1,n,l,r));
	}
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/


DZY Loves Colors

真的会谢,不记得标记清零导致WA了一天,维护加和区间覆盖标记即可

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 1000007
#define mod 1000000007
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
struct Tree
{
	int col,sum,add,box=-1;
}tr[N<<2];
int T=1,n,m,k;
void Pushup(int now,int l,int r)
{
	if(l==r)
		return;
	tr[now].sum=tr[now<<1].sum+tr[now<<1|1].sum;
	if(tr[now<<1].col==tr[now<<1|1].col)
		tr[now].col=tr[now<<1].col;
	else
		tr[now].col=-1;
}
void Push_add(int now,int l,int r,int x)
{
	tr[now].sum+=x*(r-l+1);
	tr[now].add+=x;
}
void Push_box(int now,int l,int r,int x)
{
	tr[now].col=tr[now].box=x;
}
void Pushdown(int now,int l,int r)
{
	int mid=l+((r-l)>>1);
	Push_add(now<<1,l,mid,tr[now].add);
	Push_add(now<<1|1,mid+1,r,tr[now].add);
	tr[now].add=0;
	if(tr[now].box!=-1)
	{
		Push_box(now<<1,l,mid,tr[now].box);
		Push_box(now<<1|1,mid+1,r,tr[now].box);
		tr[now].box=-1;
	}
} 
void Build(int now,int l,int r)
{
	if(l==r)
	{
		tr[now].sum=0;
		tr[now].col=l;
		tr[now].box=-1;
		return;
	}
	int mid=l+((r-l)>>1);
	Build(now<<1,l,mid);
	Build(now<<1|1,mid+1,r); 
	Pushup(now,l,r); 
}
int Search_sum(int now,int l,int r,int ll,int rr)
{
	if(ll<=l&&r<=rr)
		return tr[now].sum;
	int mid=l+((r-l)>>1);
	Pushdown(now,l,r);
	int ans=-1;
	if(rr<=mid)
		ans=Search_sum(now<<1,l,mid,ll,rr);
	if(ll>mid)
		ans=Search_sum(now<<1|1,mid+1,r,ll,rr);
	if(ans==-1)
		ans=Search_sum(now<<1,l,mid,ll,mid)+Search_sum(now<<1|1,mid+1,r,mid+1,rr);
	Pushup(now,l,r);
	return ans;
}
void Update(int now,int l,int r,int ll,int rr,int val)
{
	int mid=l+((r-l)>>1);
	if(ll<=l&&r<=rr)
	{
		if(tr[now].col!=-1)
		{
			Push_add(now,l,r,abs(val-tr[now].col));
			Push_box(now,l,r,val);
			return;
		}
		Pushdown(now,l,r);
		Update(now<<1,l,mid,ll,rr,val);
		Update(now<<1|1,mid+1,r,ll,rr,val);
		Pushup(now,l,r);
		return;
	}
	Pushdown(now,l,r);
	if(rr<=mid)
	{
		Update(now<<1,l,mid,ll,rr,val);
		Pushup(now,l,r);
		return;
	}
	if(ll>mid)
	{
		Update(now<<1|1,mid+1,r,ll,rr,val);
		Pushup(now,l,r);
		return;
	}
	Update(now<<1,l,mid,ll,mid,val);
	Update(now<<1|1,mid+1,r,mid+1,rr,val);
	Pushup(now,l,r);
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld",&n,&m);
	Build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		int opt,l,r,x;
		scanf("%lld%lld%lld",&opt,&l,&r);
		if(opt==1)
		{
			scanf("%lld",&x);
			Update(1,1,n,l,r,x);
		}
		if(opt==2)
			printf("%lldn",Search_sum(1,1,n,l,r));
	}
	return true;
}

signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*

*/


P6477 [NOI Online #2 提高组] 子序列问题

推导公式

寒假集训记录

最后树状数组实现区间修改,区间查询

寒假集训记录

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1000007
#define M 1000007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m;
int a[N],b[N],lst[N],d[N];
int tr1[N<<2],tr2[N<<2];
int lowbit(int x)
{
	return x&(-x);
}
void Add(int x,int k)
{
	int tmp=x;
	while(x<=n)
	{
		tr1[x]+=k;
		tr2[x]+=k*tmp;
		x+=lowbit(x);
	}
}
int Search(int x)
{
	int ans=0,tmp=x;
	while(x)
	{
		ans+=tr1[x]*(tmp+1)-tr2[x];
		x-=lowbit(x);
	}
	return ans;
}
bool Solve()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
	{
		scanf("%lld",&a[i]);
		b[i-1]=a[i];
	}
	sort(b,b+n);
	m=unique(b,b+n)-b;
	for(int i=1;i<=n;++i)
	{
		a[i]=lower_bound(b,b+m,a[i])-b;
		lst[i]=d[a[i]];
		d[a[i]]=i;
	}
	int ans=0,now=0;
	for(int i=1;i<=n;++i)
	{
		now=(now+i-lst[i]+2*(Search(i)-Search(lst[i])))%mod;
		ans=(ans+now)%mod;
		Add(lst[i]+1,1);
		Add(i+1,-1);
	}
	printf("%lldn",ans);
	return 1;
} 
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

P5490 【模板】扫描线

对着题解写的,自己写目前写不出,之后再来补一下这个题

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 200007
#define M 1000007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Line
{
	int x,ymn,ymx,tag;
}line[N];
struct Tree
{
	int cnt,len;
}tr[N*6];
int T=1,n,m,lcnt,cnt;
int rk[N],val[N];
bool Cmp(Line x,Line y)
{
	return x.x<y.x;
}
void Pushup(int now,int l,int r)
{
	if(tr[now].cnt)
		tr[now].len=val[r+1]-val[l];
	else
		tr[now].len=tr[now<<1].len+tr[now<<1|1].len;
}
void Add(int now,int l,int r,int ll,int rr,int val)//线段树中[l,r]表示val[l]~val[r+1]这个区间 
{//目的是为了使线段树的区间都与题意匹配 
	if(ll<=l&&r<=rr)
	{
		tr[now].cnt+=val;
		Pushup(now,l,r);
		return;
	}
	int mid=l+((r-l)>>1);//不需要Pushdown,因此子节点信息是错误的,但是由于只需要知道根节点信息,因此只需要往上更新 
	if(ll<=mid)
		Add(now<<1,l,mid,ll,rr,val);
	if(rr>mid)
		Add(now<<1|1,mid+1,r,ll,rr,val);
	Pushup(now,l,r);
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
	{
		int x1,x2,y1,y2;
		scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
		line[++lcnt]=(Line){x1,min(y1,y2),max(y1,y2),1};
		line[++lcnt]=(Line){x2,min(y1,y2),max(y1,y2),-1};
		rk[++cnt]=y1;rk[++cnt]=y2;
	}
	sort(rk+1,rk+1+cnt);
	m=unique(rk+1,rk+1+cnt)-rk-1;
	cnt=0;
	for(int i=1;i<=lcnt;++i)
	{
		int pos1=lower_bound(rk+1,rk+1+m,line[i].ymx)-rk;
		int pos2=lower_bound(rk+1,rk+1+m,line[i].ymn)-rk;
		val[pos1]=line[i].ymx;
		val[pos2]=line[i].ymn;
		line[i].ymx=pos1,line[i].ymn=pos2;
		cnt=max(cnt,pos1);
	}
	sort(line+1,line+1+lcnt,Cmp);
	int ans=0;
	for(int i=1;i<lcnt;++i)
	{
		Add(1,1,lcnt,line[i].ymn,line[i].ymx-1,line[i].tag);
		ans+=tr[1].len*(line[i+1].x-line[i].x);
	}
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
*/


P6186 [NOI Online #1 提高组] 冒泡排序

有点毒瘤,之后再来做一次

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 200007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m;
int tr[N<<2];
int before[N],record[N],a[N];//before[i]表示位置i的数a[i]的前面,有多少个数比它大
int lowbit(int x)//record[i]表示,有i个数在前面比它大的数的数量
{
	return x&(-x);
}
void Add(int x,int k)
{
	while(x<=n)
	{
		tr[x]+=k;
		x+=lowbit(x);
	}
}
int Search(int x)
{
	int ans=0;
	while(x)
	{
		ans+=tr[x];
		x-=lowbit(x);
	}
	return ans;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld",&n,&m);
	int sum=0;
	for(int i=1;i<=n;++i)
	{
		scanf("%lld",&a[i]);
		before[i]=i-1-Search(a[i]);
		sum+=before[i];
		++record[before[i]];
		Add(a[i],1);
	}
	memset(tr,0,sizeof(tr));
	Add(1,sum);
	sum=0;
	for(int i=1;i<=n;++i)
	{
		sum+=record[i-1];
		Add(i+1,-(n-sum));
	}
	for(int i=1;i<=m;++i)
	{
		int opt,x;
		scanf("%lld%lld",&opt,&x);
		x=min(x,n-1);
		if(opt==1)
		{
			if(a[x]<a[x+1])
			{
				swap(a[x],a[x+1]);
				swap(before[x],before[x+1]);
				++before[x+1];
				Add(before[x+1]+1,-1);
				Add(1,1);
			}
			else
			{
				swap(a[x],a[x+1]);
				swap(before[x],before[x+1]);
				Add(before[x]+1,1);
				--before[x];
				Add(1,-1);
			}
		}
		else
			printf("%lldn",Search(x+1));
	}
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/

![P6186 P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并

动态开点线段树+线段树合并+树上差分

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 19
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt;
}edge[N<<1];
struct Tree
{
	int ls,rs,sum,mxnum;
}tr[N*80];
int T=1,n,m,ecnt,tcnt;
int head[N],fa[N][M],dep[N],rt[N],ans[N];
void Add(int u,int v)
{
	edge[++ecnt]={v,head[u]};
	head[u]=ecnt;
}
void Dfs(int u,int father)
{
	fa[u][0]=father;
	dep[u]=dep[father]+1;
	for(int i=1;i<M;++i)
		fa[u][i]=fa[fa[u][i-1]][i-1];
	for(int i=head[u];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(v==father)
			continue;
		Dfs(v,u);
	}
}
int Get_lca(int x,int y)
{
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=M-1;i>=0;--i)
		if(dep[fa[x][i]]>=dep[y])
			x=fa[x][i];
	if(x==y)	return x;
	for(int i=M-1;i>=0;--i)
		if(fa[x][i]!=fa[y][i])
			x=fa[x][i],y=fa[y][i];
	return fa[x][0];	
}
void Pushup(int now)
{
	if(!tr[now].ls)
	{
		tr[now].sum=tr[tr[now].rs].sum;
		tr[now].mxnum=tr[tr[now].rs].mxnum;
		return;
	}
	if(!tr[now].rs)
	{
		tr[now].sum=tr[tr[now].ls].sum;
		tr[now].mxnum=tr[tr[now].ls].mxnum;
		return;
	}
	if(tr[tr[now].ls].sum>=tr[tr[now].rs].sum)
	{
		tr[now].sum=tr[tr[now].ls].sum;
		tr[now].mxnum=tr[tr[now].ls].mxnum;
	}
	else
	{
		tr[now].sum=tr[tr[now].rs].sum;
		tr[now].mxnum=tr[tr[now].rs].mxnum;
	}
} 
void Update(int &now,int l,int r,int pos,int val)
{
	if(!now) now=++tcnt;
	if(l==r)
	{
		tr[now].sum+=val;
		tr[now].mxnum=pos;
		return;
	}
	int mid=l+((r-l)>>1);
	if(pos<=mid) Update(tr[now].ls,l,mid,pos,val);
	else Update(tr[now].rs,mid+1,r,pos,val);
	Pushup(now);
}
int Merge(int x,int y,int l,int r)
{
	if(!x||!y) return x+y;
	if(l==r)
	{
		tr[x].sum+=tr[y].sum;
		return x;
	}
	int mid=l+((r-l)>>1);
	tr[x].ls=Merge(tr[x].ls,tr[y].ls,l,mid);
	tr[x].rs=Merge(tr[x].rs,tr[y].rs,mid+1,r);
	Pushup(x);
	return x;
} 
void Search(int u,int father)
{
	for(int i=head[u];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(v==father)
			continue;
		Search(v,u);
		rt[u]=Merge(rt[u],rt[v],1,100000);
	}
	ans[u]=tr[rt[u]].mxnum;
	if(tr[rt[u]].sum==0)
		ans[u]=0;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<n;++i)
	{
		int in1,in2;
		scanf("%lld%lld",&in1,&in2);
		Add(in1,in2);
		Add(in2,in1);
	}
	Dfs(1,0);
	for(int i=1;i<=m;++i)
	{
		int in1,in2,in3;
		scanf("%lld%lld%lld",&in1,&in2,&in3);
		int lca=Get_lca(in1,in2);
		Update(rt[in1],1,100000,in3,1);
		Update(rt[in2],1,100000,in3,1);
		Update(rt[lca],1,100000,in3,-1);
		Update(rt[fa[lca][0]],1,100000,in3,-1);
	}
	Search(1,0);
	for(int i=1;i<=n;++i)
		printf("%lldn",ans[i]);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/


DP练习

LCS

暴力DP,(O(n^2))

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 3007
#define M 500007
#define mod 100003
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,k;
int f[N][N],ans[N][N]; 
string s,t;
void Print(int l,int r)
{
	if(!l||!r)
		return;
	if(ans[l][r]==1)
	{
		Print(l-1,r-1);
		printf("%c",s[l]);
	}
	if(ans[l][r]==2)
		Print(l-1,r);
	if(ans[l][r]==3)
		Print(l,r-1);
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	cin>>s>>t;
	n=s.size();m=t.size();
	s=" "+s,t=" "+t;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
		{
			if(s[i]==t[j])
			{
				f[i][j]=f[i-1][j-1]+1;
				ans[i][j]=1;
				continue;
			}
			if(f[i-1][j]>f[i][j-1])
			{
				f[i][j]=f[i-1][j];
				ans[i][j]=2;
			}
			else
			{
				f[i][j]=f[i][j-1];
				ans[i][j]=3;
			}
		}
	Print(n,m);
	printf("n");
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*
*/


P1064 [NOIP2006 提高组] 金明的预算方案

有限制的01背包,感觉结构体写的好繁杂。。。。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 40007
#define M 500007
#define mod 100003
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Node
{
	int num,w,v;
	bool fir;
	int son[3];
	void Init(int x,int y)
	{
		w=x,v=y;
	}
}a[N];
int T=1,n,m,k,cnt;
int f[N];
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=m;++i)
	{
		int in1,in2,in3;
		scanf("%lld%lld%lld",&in1,&in2,&in3);
		a[i].Init(in1,in2);
		if(!in3)
			a[i].fir=1;
		else
			a[in3].son[++a[in3].num]=i;
	}
	for(int i=1;i<=m;++i)
	{
		if(!a[i].fir)
			continue;
		for(int j=n;j>=a[i].w;--j)
		{
			f[j]=max(f[j],f[j-a[i].w]+a[i].v*a[i].w);
			if(a[i].num>=1&&j>=a[i].w+a[a[i].son[1]].w)
				f[j]=max(f[j],f[j-a[i].w-a[a[i].son[1]].w]+a[i].w*a[i].v+a[a[i].son[1]].w*a[a[i].son[1]].v);
			if(a[i].num>=2)
			{
				if(j>=a[i].w+a[a[i].son[1]].w+a[a[i].son[2]].w)
					f[j]=max(f[j],f[j-a[i].w-a[a[i].son[1]].w-a[a[i].son[2]].w]+a[i].w*a[i].v+a[a[i].son[1]].w*a[a[i].son[1]].v+a[a[i].son[2]].w*a[a[i].son[2]].v);
				if(j>=a[i].w+a[a[i].son[2]].w)
					f[j]=max(f[j],f[j-a[i].w-a[a[i].son[2]].w]+a[i].w*a[i].v+a[a[i].son[2]].w*a[a[i].son[2]].v);
			}
		}
	}
	printf("%lldn",f[n]);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
*/


P1352 没有上司的舞会

很经典的树形dp,没啥好说的

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 10007
#define M 500007
#define mod 100003
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt;
}edge[N<<1];
int T=1,n,ecnt;
int head[N],val[N],f[N][2];
void Add(int u,int v)
{
	edge[++ecnt]=(Edge){v,head[u]};
	head[u]=ecnt;
}
void Dp(int u,int fa)
{
	f[u][1]=val[u];
	for(int i=head[u];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(v==fa)
			continue;
		Dp(v,u);
		f[u][0]+=max(f[v][0],f[v][1]);
		f[u][1]+=f[v][0]; 
	}
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
		scanf("%lld",&val[i]);
	for(int i=1;i<n;++i)
	{
		int u,v;
		scanf("%lld%lld",&u,&v);
		Add(u,v);
		Add(v,u);
	}
	Dp(1,0);
	printf("%lldn",max(f[1][1],f[1][0]));
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
*/


P1819 公共子序列

感觉题解有问题,但是问题也不是很大,子序列自动机,处理出nxt数组,进行记忆化搜索即可

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 157
#define M 27
#define mod 100000000
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,ecnt;
string a,b,c;
int la,lb,lc;
int nxta[N][M],nxtb[N][M],nxtc[N][M];
int f[N][N][N];
void Init_nxt(int nxt[N][M],int len,string x)
{
	for(int i=len-1;i>=0;--i)
	{
		for(int j=0;j<26;++j)
			nxt[i][j]=nxt[i+1][j];
		nxt[i][x[i+1]-'a']=i+1;
	}
}
int Dfs(int x,int y,int z)
{
	if(f[x][y][z]) return f[x][y][z];
	if(x&&y&&z)//个人理解是&&,虽然题解是||,只有同时不为0才表示当前这个字符也是个公共子序列 
		++f[x][y][z];//但是由于下面的if使得||也能通过,因为x,y,z必不为0(个人理解) 
	for(int i=0;i<26;++i)
		if(nxta[x][i]&&nxtb[y][i]&&nxtc[z][i])
			f[x][y][z]=(f[x][y][z]+Dfs(nxta[x][i],nxtb[y][i],nxtc[z][i]))%mod;
	return f[x][y][z]%mod;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	cin>>a>>b>>c;
	la=a.size(),lb=b.size(),lc=c.size();
	a=" "+a,b=" "+b,c=" "+c;
	Init_nxt(nxta,la,a);
	Init_nxt(nxtb,lb,b);
	Init_nxt(nxtc,lc,c);
	printf("%lldn",Dfs(0,0,0)%mod);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
*/


Kavi on Pairing Duty

对于我来说还是有点难想到

合法的匹配一定是外面若干层,每一层都是若干个等长的圆弧,最里面一层为若干个等长的圆弧。(引用)

由于每个圆弧要等长,所以假设要匹配 l 个圆弧,则每个圆弧的长度必须是 l 的因数。而对于每一确定的长度,则有唯一对应的一种匹配的方案。所以内层的方案数为 d(l)。(引用)

先把n个点分成里外两部分,里面这部分是等大互不相交的,外面的方案数是(2^{k-1})(供我自己理解,解释需要图,不想画了)

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1000007
#define M 27
#define mod 998244353
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,ecnt;
int d[N];
int Pow(int x,int y)
{
	int ans=1,cnt=x;
	while(y)
	{
		if(y&1)
			ans*=cnt;
		cnt*=cnt;
		ans%=mod;
		cnt%=mod;
		y>>=1;
	}
	return ans;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		for(int j=i;j<=n;j+=i) ++d[j];
	int ans=0;
	for(int i=1;i<=n;++i) 
		ans=(ans+Pow(2,max(n-i-1,(int)0))*d[i]%mod)%mod;
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
*/



P1273 有线电视网

树形背包,要注意初始化负无穷

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 3007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt,cst;
}edge[N<<1];
int T=1,n,m,ecnt;
int val[N],head[N],f[N][N];
void Add(int u,int v,int w)
{
	edge[++ecnt]=(Edge){v,head[u],w};
	head[u]=ecnt;
}
int Dp(int u,int fa)
{
	if(u>n-m)
	{
		f[u][1]=val[u];
		return 1;
	}
	int num=0;
	for(int i=head[u];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(v==fa) continue;
		int now=Dp(v,u);
		num+=now;
		for(int j=num;j>=0;--j)
			for(int k=0;k<=now;++k)
				if(j-k>=0)
					f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]-edge[i].cst);
	}
	return num;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n-m;++i)
	{
		int in1;
		scanf("%lld",&in1);
		for(int j=1;j<=in1;++j)
		{
			int in2,in3;
			scanf("%lld%lld",&in2,&in3);
			Add(i,in2,in3);
			Add(in2,i,in3);
		}
	}
	for(int i=n-m+1;i<=n;++i)
		scanf("%lld",&val[i]);
	memset(f,inc,sizeof(f));
	for(int i=1;i<=n;++i)
		f[i][0]=0;
	Dp(1,0);
	for(int i=m;i;--i)
		if(f[1][i]>=0)
		{
			printf("%lldn",i);
			return true;
		}
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/


P2704 [NOI2001] 炮兵阵地

经典状压,用滚动数组,记得要特判n=1时

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 107
#define M 10
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m;
int a[N][M],num[N],f[1<<M][1<<M][2];
int Get_num(int now)
{
	int ans=0;
	while(now)
	{
		if(now&1)
			++ans;
		now>>=1;
	}
	return ans;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
		{
			num[i]<<=1;
			scanf(" %c",&a[i][j]);
			if(a[i][j]=='H')
				num[i]+=1;
		}
	if(n==1)
	{
		int ans=0;
		for(int i=0;i<(1<<m);++i)
		{
			if((i&num[1])||(i&(i>>1))||(i&(i>>2)))
				continue;
			ans=max(ans,Get_num(i));
		}
		printf("%lldn",ans);
		return 1;
	}
	for(int i=0;i<(1<<m);++i)
	{
		
		for(int j=0;j<(1<<m);++j)
		{
			if((j&num[2])||(j&(j>>1))||(j&(j>>2))||(i&j))
				continue;
			f[j][i][0]=Get_num(j)+Get_num(i);
		}
	}
	for(int i=3;i<=n;++i)
	{
		for(int now=0;now<(1<<m);++now)
		{
			if((now&num[i])||(now&(now>>1))||(now&(now>>2)))
				continue;
			int tmp=Get_num(now);
			for(int lst2=0;lst2<(1<<m);++lst2)
			{
				if((lst2&num[i-2])||(lst2&(lst2>>1))||(lst2&(lst2>>2))||(now&lst2))
					continue;
				for(int lst1=0;lst1<(1<<m);++lst1)
				{
					if((lst1&num[i-1])||(lst1&(lst1>>1))||(lst1&(lst1>>2))||(lst1&lst2)||(now&lst1))
						continue;
					f[now][lst1][i%2]=max(f[now][lst1][i%2],f[lst1][lst2][(i+1)%2]+tmp);
				}
			}
		}
	}
	int ans=0;
	for(int i=0;i<(1<<m);++i)
	{
		if((i&num[n-1])||(i&(i>>1))||(i&(i>>2)))
			continue;
		for(int j=0;j<(1<<m);++j)
		{
			if((j&num[n])||(j&(j>>1))||(j&(j>>2))||(i&j))
				continue;
			ans=max(ans,f[j][i][n%2]);
		}
	}
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
1 1
P

*/

P1081 [NOIP2012 提高组] 开车旅行

题是真的恶心,被STL搞破防了好久,思路是倍增优化预处理,然后模拟

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 20
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Node
{
	int id,val;
	bool operator <(const Node x) const
	{
		return val<x.val; 
	}
};
int T=1,n,x0,m;
int a[N],nxt[N][M][2],disa[N][M][2],disb[N][M][2];//nxt[i][j][k]表示从第i个地方开始由k先开车,走$2^j$走到的地方
multiset<Node> st;
void Init()
{
	st.insert((Node){n+1,(int)-inf});
	st.insert((Node){n+1,(int)-inf});
	st.insert((Node){0,(int)inf});
	st.insert((Node){0,(int)inf});
	for(int i=n;i;--i)
	{
		st.insert((Node){i,a[i]});
		auto pos=st.lower_bound((Node){i,a[i]});
		--pos;Node l1=*pos;--pos;Node l2=*pos;++pos;++pos;++pos;Node r1=*pos;++pos;Node r2=*pos;
		if(abs(r1.val-a[i])<abs(l1.val-a[i]))
		{
			nxt[i][0][1]=r1.id;
			disb[i][0][1]=abs(r1.val-a[i]);
			if(abs(r2.val-a[i])<abs(l1.val-a[i]))
			{
				nxt[i][0][0]=r2.id;
				disa[i][0][0]=abs(r2.val-a[i]);
			}
			else
			{
				nxt[i][0][0]=l1.id;
				disa[i][0][0]=abs(l1.val-a[i]);
			}
		}	
		else
		{
			nxt[i][0][1]=l1.id;
			disb[i][0][1]=abs(l1.val-a[i]);
			if(abs(l2.val-a[i])<=abs(r1.val-a[i]))
			{
				nxt[i][0][0]=l2.id;
				disa[i][0][0]=abs(l2.val-a[i]);
			}
			else
			{
				nxt[i][0][0]=r1.id;
				disa[i][0][0]=abs(r1.val-a[i]);
			}
		}		
	}
	for(int i=1;i<M;++i)
	{
		for(int j=1;j<=n;++j)
		{
			for(int k=0;k<=1;++k)
			{
				if(i==1)
				{
					nxt[j][i][k]=nxt[nxt[j][i-1][k]][i-1][k^1];
					disa[j][i][k]=disa[nxt[j][i-1][k]][i-1][k^1]+disa[j][i-1][k];
					disb[j][i][k]=disb[nxt[j][i-1][k]][i-1][k^1]+disb[j][i-1][k];
				}
				else
				{
					nxt[j][i][k]=nxt[nxt[j][i-1][k]][i-1][k];
					disa[j][i][k]=disa[nxt[j][i-1][k]][i-1][k]+disa[j][i-1][k];
					disb[j][i][k]=disb[nxt[j][i-1][k]][i-1][k]+disb[j][i-1][k];
				}
			}
		}
	}
}
int la,lb;
void Calc(int s,int len)
{
	int now=s;
	la=0,lb=0;
	for(int i=M-1;i>=0;--i)
	{
		if(nxt[now][i][0]&&la+lb+disa[now][i][0]+disb[now][i][0]<=len)
		{
			la+=disa[now][i][0];
			lb+=disb[now][i][0];
			now=nxt[now][i][0];
		}
	}
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
		scanf("%lld",&a[i]);
	scanf("%lld%lld",&x0,&m);
	Init();
	double ans=inf;
	int pos=0;
	for(int i=1;i<=n;++i)
	{
		Calc(i,x0);
		double now=(double)la/((double)lb);
		if(now<ans)
		{
			ans=now;pos=i;
		}
		else
			if(ans==now&&a[pos]<a[i])
				pos=i;
	}
	printf("%lldn",pos);
	for(int i=1;i<=m;++i)
	{
		int in1,in2;
		scanf("%lld%lld",&in1,&in2);
		Calc(in1,in2);
		printf("%lld %lldn",la,lb);
	}
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}

/*

*/


Multiplicity

滚动数组dp,f[i]表示序列长度为i时的方案数

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n;
int a[N],f[N*10];
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
		scanf("%lld",&a[i]);
	f[0]=1;
	for(int i=1;i<=n;++i)
	{
		vector<int> d;
		int nn=sqrt(a[i]);
		for(int j=1;j<=nn;++j)
			if(a[i]%j==0)
			{
				int k=a[i]/j;
				d.push_back(k);
				if(k!=j)
					d.push_back(j);
			}
		sort(d.begin(),d.end());
		for(int j=d.size()-1;j>=0;--j)
		{
			f[d[j]]=f[d[j]]+f[d[j]-1];
			f[d[j]]%=mod;
		}
	}
	int ans=0;
	for(int i=1;i<=n;++i)
		ans+=f[i],ans%=mod;
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


Sequence Sorting

真心想不到这个做法,挺玄乎的。

记录每个数最左端和最右端位置,找到最长的非递减序列,答案是数字类别总数-最长长度

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n;
int a[N],l[N],r[N];
bool Solve()
{
 	//freopen("test.in","r",stdin);
 	scanf("%lld",&n);
    for(int i=1;i<=n;++i) 
		l[i]=0,r[i]=0;
    for(int i=1;i<=n;++i) 
	{
        scanf("%lld",&a[i]);
        if(!l[a[i]]) 
			l[a[i]]=i;
        r[a[i]]=i;
    }
    int cnt=0,last=0,sum=0,ans=0;
    for(int i=1;i<=n;++i) 
        if(l[i]) 
		{
            if(last<l[i])
                ++cnt;
            else
                cnt=1;
            ans=max(cnt,ans);
            ++sum;
            last=r[i];
        }
    printf("%lldn",sum-ans);
	return true;
}
signed main()
{
	scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


图论

P3385 【模板】负环

虽然spfa死了,但不影响我继续用

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt,w;
}edge[M<<1];
int T=1,n,m,cnt;
int head[N],num[N],dis[N];
void Add(int u,int v,int w)
{
	edge[++cnt]=(Edge){v,head[u],w};
	head[u]=cnt;
}
bool Spfa(int s)
{
	queue<int> dui;
	dui.push(s);
	num[s]=1;
	dis[s]=0;
	while(!dui.empty())
	{
		int u=dui.front();
		dui.pop();
		for(int i=head[u];i;i=edge[i].nxt)
		{
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].w)
			{
				dis[v]=dis[u]+edge[i].w;
				++num[v];
				if(num[v]>n)
					return 1;
				dui.push(v);
			}
		}
	}
	return 0;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	memset(num,0,sizeof(num));
	memset(dis,0x3f3f3f3f,sizeof(dis));
	memset(head,0,sizeof(head));
	cnt=0;
	//printf("%d %dn",dis[0],inf);
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=m;++i)
	{
		int u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		Add(u,v,w);
		if(w>=0)
			Add(v,u,w);
	}
	printf("%sn",Spfa(1)?"YES":"NO");
	return true;
}
signed main()
{
	scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P5960 【模板】差分约束算法

将不等式看成最短路松弛,于是新建一个源点,与所有点连接,跑最短路,无环则有解

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt,w;
}edge[M<<1];
int T=1,n,m,ecnt;
int head[N],num[N],dis[N];
void Add(int u,int v,int w)
{
	edge[++ecnt]=(Edge){v,head[u],w};
	head[u]=ecnt;
}
bool Spfa(int s)
{
	queue<int> que;
	que.push(s);
	num[s]=1;
	dis[s]=0;
	while(!que.empty())
	{
		int u=que.front();
		que.pop();
		for(int i=head[u];i;i=edge[i].nxt)
		{
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].w)
			{
				dis[v]=dis[u]+edge[i].w;
				++num[v];
				if(num[v]>n+1)
					return 1;
				que.push(v);
			}
		}
	}
	return 0;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	memset(dis,0x3f3f3f3f,sizeof(dis));
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;++i)
		Add(0,i,0);
	for(int i=1;i<=m;++i)
	{
		int u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		Add(v,u,w);
	}
	if(Spfa(0))
	{
		printf("NOn");
		return 1; 
	}
	else
	{
		for(int i=1;i<=n;++i)
			printf("%lld ",dis[i]);
		printf("n");
	}
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


Directing Edges

开了long long超时了。。调了好一会。
思路是拓扑排序得到拓扑序,无向边改为拓扑序小的节点指向拓扑序大的节点。
无解的情况显然为有向边成环的情况。

点击查看代码
#include<bits/stdc++.h>
//#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 200007
#define M 200007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt;
}edge[M];
int T=1,n,m,ecnt;
int head[N],indeg[N],tnum[N],a[M],b[M],c[M];
void Add(int u,int v)
{
	edge[++ecnt]=(Edge){v,head[u]};
	head[u]=ecnt;
	++indeg[v];
}
bool Topo()
{
	int cnt=0;
	queue<int> que;
	for(int i=1;i<=n;++i)
		if(!indeg[i])
			que.push(i);
	while(!que.empty())
	{
		int u=que.front();
		que.pop();
		tnum[u]=++cnt;
		for(int i=head[u];i;i=edge[i].nxt)
		{
			int v=edge[i].to;
			--indeg[v];
			if(!indeg[v])
				que.push(v);
		}
	}
	return cnt==n;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
 	memset(head,0,sizeof(head));
 	memset(indeg,0,sizeof(indeg));
 	memset(tnum,0,sizeof(tnum));
 	ecnt=0;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d%d",&c[i],&a[i],&b[i]);
		if(c[i])
			Add(a[i],b[i]);
	}
	if(Topo())
	{
		printf("YESn");
		for(int i=1;i<=m;++i)
		{
			if(c[i])
				printf("%d %dn",a[i],b[i]);
			else
			{
				if(tnum[a[i]]<tnum[b[i]])
					printf("%d %dn",a[i],b[i]);
				else
					printf("%d %dn",b[i],a[i]);
			}
		}
	}
	else
		printf("NOn");
	return true;
}
signed main()
{
	scanf("%d",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P2047 [NOI2007] 社交网络

完全没想到用floyed,几年没用了,以后看到这种数据范围,以及要求每两个点的最短路有关的就要想到floyed

num[i][j]为i到j的最短路径条数

维护好后答案很好求了

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 107
#define M 4507
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,ecnt;
int dis[N][N],num[N][N];
double ans[N];
bool Solve()
{
 	//freopen("test.in","r",stdin);
 	scanf("%lld%lld",&n,&m);
 	for(int i=1;i<=n;++i)
 		for(int j=1;j<=n;++j)
 			dis[i][j]=(i==j)?0:inf;
 	for(int i=1;i<=m;++i)
 	{
 		int u,v,w;
 		scanf("%lld%lld%lld",&u,&v,&w);
 		dis[u][v]=dis[v][u]=w;
 		num[u][v]=num[v][u]=1;
	}
	for(int k=1;k<=n;++k)
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
			{
				if(dis[i][k]==inf||dis[k][j]==inf)
					continue;
				if(dis[i][j]>dis[i][k]+dis[k][j])
				{
					dis[i][j]=dis[i][k]+dis[k][j];
					num[i][j]=num[i][k]*num[k][j];
					continue;
				}
				if(dis[i][j]==dis[i][k]+dis[k][j])
					num[i][j]+=num[i][k]*num[k][j];
			}
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
		{
			if(i==j)
				continue;
			for(int k=1;k<=n;++k)
			{
				if(i==k||j==k)
					continue;
				if(dis[i][j]==dis[i][k]+dis[k][j])
					ans[k]+=(((double)num[i][k])*((double)num[k][j]))/((double)num[i][j]);
			}
		}
	for(int i=1;i<=n;++i)
		printf("%.3lfn",ans[i]);
	return true;
}
signed main()
{
	//scanf("%d",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P2662 牛场围栏

还是第一次做同余类最短路,这个数组大小WA了几次,觉得下面这个题解讲的很清楚了,自己就不多废话了,反正也不是自己想出来的做法

寒假集训记录

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1000007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m;
int a[N],dis[N];
bool vis[N];
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;++i)
        scanf("%lld",&a[i]);
    int nn=n;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            if(a[i]-j>0)
                a[++nn]=a[i]-j;
    sort(a+1,a+nn+1);
    int ok=1;
    for(int i=2;i<=nn;++i)
        if(a[i]%a[1]!=0)
        {
        	ok=0;
        	break;
		}
	if(ok)
		return 0;
    nn=unique(a+1,a+nn+1)-a-1;
    memset(dis,0x3f,sizeof(dis));
    dis[0]=0;
    queue<int> que;
    que.push(0);
    vis[0]=1;
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        for(int i=2;i<=nn;++i)
            if(dis[(u+a[i])%a[1]]>dis[u]+a[i])
            {
                dis[(u+a[i])%a[1]]=dis[u]+a[i];
                if(!vis[(u+a[i])%a[1]])
                {
                    vis[(u+a[i])%a[1]]=1;
                    que.push((u+a[i])%a[1]);
                }
            }
        vis[u]=0;
    }
    int ans=0;
    for(int i=1;i<a[1];++i)
        ans=max(ans,dis[i]);
    printf("%lldn",ans-a[1]);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P1993 小 K 的农场

和差分约束模板题差不多,只需要记住当Xa-Xb<=c时,连一条从b到a权值为c的边,如果是相等则互相连一条权值为0的边

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt,w;
}edge[M<<1];
int T=1,n,m,ecnt;
int head[N],num[N],dis[N];
void Add(int u,int v,int w)
{
	edge[++ecnt]=(Edge){v,head[u],w};
	head[u]=ecnt;
}
bool Spfa(int s)
{
	queue<int> que;
	que.push(s);
	num[s]=1;
	dis[s]=0;
	while(!que.empty())
	{
		int u=que.front();
		que.pop();
		for(int i=head[u];i;i=edge[i].nxt)
		{
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].w)
			{
				dis[v]=dis[u]+edge[i].w;
				++num[v];
				if(num[v]>n+2)
					return 1;
				que.push(v);
			}
		}
	}
	return 0;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	memset(dis,0x3f3f3f3f,sizeof(dis));
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;++i)
		Add(0,i,0),Add(i,n+1,0);
	for(int i=1;i<=m;++i)
	{
		int opt,u,v,w;
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld%lld%lld",&u,&v,&w);
			Add(u,v,-w);
		}
		if(opt==2)
		{
			scanf("%lld%lld%lld",&u,&v,&w);
			Add(v,u,w);
		}
		if(opt==3)
		{
			scanf("%lld%lld",&u,&v);
			Add(v,u,0);
			Add(u,v,0);
		}
	}
	if(Spfa(0))
		printf("Non");
	else
		printf("Yesn");
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P4568 [JLOI2011] 飞行路线

分层最短路模板

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt,dis;
}edge[M*17];
struct Node
{
	int val,id;
	bool operator < (const Node x) const
	{
		return val>x.val;
	};
}num[N];
int T=1,n,m,k,s,t,ecnt;
int head[N*17],dis[N*17];
bool vis[N*17];
int Dij()
{
	priority_queue<Node> pque;
	pque.push((Node){0,s});
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0;
	while(!pque.empty())
	{
		int u=pque.top().id;
		pque.pop();
		if(vis[u])
			continue;
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].nxt)
		{
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].dis)
			{
				dis[v]=dis[u]+edge[i].dis;
				pque.push((Node){dis[v],v});
			}
		}
	}
}
void Add(int u,int v,int w)
{
	edge[++ecnt]=(Edge){v,head[u],w};
	head[u]=ecnt; 
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld%lld%lld%lld",&n,&m,&k,&s,&t);
	for(int i=1;i<=m;++i)
	{
		int u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		for(int j=0;j<=k;++j)
		{
			Add(u+j*n,v+j*n,w);
			Add(v+j*n,u+j*n,w);
		}
		for(int j=1;j<=k;++j)
		{
			Add(u+(j-1)*n,v+j*n,0);
			Add(v+(j-1)*n,u+j*n,0);
		}
	}
	for(int i=1;i<=k;++i)
	{
		Add(t+(i-1)*n,t+i*n,0);
	}
	Dij();
	//for(int i=1;i<=n;++i)
	//	printf("%lldn",dis[i]);
	printf("%lldn",dis[t+k*n]);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/



P3403 跳楼机

同余类最短路,记dis[i]为通过第二和第三种操作到达的最小楼层h,其中h%x=i。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt,dis;
}edge[M];
struct Node
{
	int val,id;
	bool operator < (const Node x) const
	{
		return val>x.val;
	};
}num[N];
int T=1,n,x,y,z,ecnt;
int head[N],dis[N];
bool vis[N];
int Dij()
{
	priority_queue<Node> pque;
	pque.push((Node){1,1});
	memset(dis,0x3f,sizeof(dis));
	dis[1]=1;//同余类最短路,记dis[i]为通过第二和第三种操作到达的最小楼层h,其中h%x=i。
	while(!pque.empty())
	{
		int u=pque.top().id;
		pque.pop();
		if(vis[u])
			continue;
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].nxt)
		{
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].dis)
			{
				dis[v]=dis[u]+edge[i].dis;
				pque.push((Node){dis[v],v});
			}
		}
	}
}
void Add(int u,int v,int w)
{
	edge[++ecnt]=(Edge){v,head[u],w};
	head[u]=ecnt; 
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld%lld%lld",&n,&x,&y,&z);
	if(x==1||y==1||z==1)
	{
		printf("%lldn",n);
		return 1;
	}
	for(int i=0;i<x;++i)
	{
		Add(i,(i+y)%x,y);
		Add(i,(i+z)%x,z);
	}
	Dij();
	int ans=0;
	for(int i=0;i<x;++i)
		if(dis[i]<=n)
			ans+=(n-dis[i])/x+1;
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/



P2939 [USACO09FEB]Revamping Trails G

和上面那个分层最短路一模一样,不多废话了

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt,dis;
}edge[M*27];
struct Node
{
	int val,id;
	bool operator < (const Node x) const
	{
		return val>x.val;
	};
};
int T=1,n,m,k,s,t,ecnt;
int head[N*27],dis[N*27];
bool vis[N*27];
int Dij()
{
	priority_queue<Node> pque;
	pque.push((Node){0,s});
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0;
	while(!pque.empty())
	{
		int u=pque.top().id;
		pque.pop();
		if(vis[u])
			continue;
		vis[u]=1;
		for(int i=head[u];i;i=edge[i].nxt)
		{
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].dis)
			{
				dis[v]=dis[u]+edge[i].dis;
				pque.push((Node){dis[v],v});
			}
		}
	}
}
void Add(int u,int v,int w)
{
	edge[++ecnt]=(Edge){v,head[u],w};
	head[u]=ecnt; 
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld%lld",&n,&m,&k);
	s=1,t=n; 
	for(int i=1;i<=m;++i)
	{
		int u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		for(int j=0;j<=k;++j)
		{
			Add(u+j*n,v+j*n,w);
			Add(v+j*n,u+j*n,w);
		}
		for(int j=1;j<=k;++j)
		{
			Add(u+(j-1)*n,v+j*n,0);
			Add(v+(j-1)*n,u+j*n,0);
		}
	}
	for(int i=1;i<=k;++i)
		Add(t+(i-1)*n,t+i*n,0);
	Dij();
	//for(int i=1;i<=n;++i)
	//	printf("%lldn",dis[i]);
	printf("%lldn",dis[t+k*n]);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P4674 [BalticOI 2016 day1]Bosses

显然BFS搜索树会优,看到数据范围提示可以每个点做根来一次BFS,但是统计答案确实是没想到,下面有种这种统计方法的解释

寒假集训记录

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 500007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt;
}edge[M];
int T=1,n,ecnt;
int head[N],dep[N];
bool vis[N];
int Bfs(int s)
{
	int sum=1,cnt=1;
	queue<int> que;
	memset(dep,0,sizeof(dep));
	memset(vis,0,sizeof(vis));
	que.push(s);
	vis[s]=1;
	dep[s]=1;
	while(!que.empty())
	{
		int u=que.front();
		que.pop();
		for(int i=head[u];i;i=edge[i].nxt)
		{
			int v=edge[i].to;
			if(vis[v])
				continue;
			vis[v]=1;
			dep[v]=dep[u]+1;
			sum+=dep[v];
			++cnt;
			que.push(v);
		}
	}
	return cnt<n?inf:sum;
}
void Add(int u,int v)
{
	edge[++ecnt]=(Edge){v,head[u]};
	head[u]=ecnt; 
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
	{
		int opt;
		scanf("%lld",&opt);
		for(int j=1;j<=opt;++j)
		{
			int in;
			scanf("%lld",&in);
			Add(in,i);
		}
	}
	int ans=inf;
	for(int i=1;i<=n;++i)
		ans=min(ans,Bfs(i));
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P3008 [USACO11JAN]Roads and Planes G

非常有意义的一个题,思路是拓扑+dij最短路。

道路和航线分别存图,道路图为很多个正权连通块,里面进行dij最短路。

再用拓扑来从一个连通块传到下一个连通块

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 25007
#define M 50007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt,dis;
}edge1[M<<1],edge2[M];
struct Node
{
	int dis,id;
	bool operator <(const Node a)const
	{
		return dis>a.dis;
	}
};
int T=1,n,m1,m2,s,ecnt1,ecnt2,bcnt;
int belong[N],dis[N],indeg[N];
bool vis[N];
int head1[N],head2[N]; 
vector<int> vec[N];
void Add1(int u,int v,int w)
{
	edge1[++ecnt1]=(Edge){v,head1[u],w};
	head1[u]=ecnt1;
}
void Add2(int u,int v,int w)
{
	edge2[++ecnt2]=(Edge){v,head2[u],w};
	head2[u]=ecnt2;
}
void Dfs(int u,int num)
{
	belong[u]=num;
	vec[num].push_back(u);
	for(int i=head1[u];i;i=edge1[i].nxt)
	{
		int v=edge1[i].to;
		if(belong[v])
			continue;
		Dfs(v,num);
	}
}
void Topo_dij()
{
	for(int i=1;i<=ecnt2;++i)
		++indeg[belong[edge2[i].to]];
	queue<int> que;
	for(int i=1;i<=bcnt;++i)
		if(!indeg[i])
			 que.push(i);
	dis[s]=0;
	while(!que.empty())
	{
		int now=que.front();
		que.pop();
		priority_queue<Node> kque;
		for(int i=0;i<vec[now].size();++i)
			if(dis[vec[now][i]]<dis[0])
				kque.push((Node){dis[vec[now][i]],vec[now][i]});
		while(!kque.empty())
		{
			int u=kque.top().id;
			kque.pop();
			if(vis[u])
				continue;
			vis[u]=1;
			for(int i=head1[u];i;i=edge1[i].nxt)
			{
				int v=edge1[i].to;
				if(dis[v]>dis[u]+edge1[i].dis)
				{
					dis[v]=dis[u]+edge1[i].dis;
					kque.push((Node){dis[v],v});
				}
			}
			for(int i=head2[u];i;i=edge2[i].nxt)
			{
				int v=edge2[i].to;
				if(dis[v]>dis[u]+edge2[i].dis)
					dis[v]=dis[u]+edge2[i].dis;
			}
		}
		for(int i=0;i<vec[now].size();++i)
		{
			for(int j=head2[vec[now][i]];j;j=edge2[j].nxt)
			{
				int v=edge2[j].to;
				--indeg[belong[v]];
				if(!indeg[belong[v]])
					que.push(belong[v]);
			}
		}
	}
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld%lld%lld",&n,&m1,&m2,&s);
	for(int i=1;i<=m1;++i)
	{
		int u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		Add1(u,v,w);
		Add1(v,u,w);
	}
	for(int i=1;i<=m2;++i)
	{
		int u,v,w;
		scanf("%lld%lld%lld",&u,&v,&w);
		Add2(u,v,w);
	}
	for(int i=1;i<=n;++i)
		if(!belong[i])
			Dfs(i,++bcnt);
	memset(dis,0x3f,sizeof(dis));
	Topo_dij();
	for(int i=1;i<=n;++i)
		if(dis[i]>=dis[0])
			printf("NO PATHn");
		else
			printf("%lldn",dis[i]);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


数论

P3383 【模板】线性筛素数

欧拉筛板子

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100000007
#define M 10000007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,ecnt;
int a[N],prime[N];
bool vis[N];
void Prim()
{
	int cnt=0;
	vis[0]=vis[1]=1; 
	for(int i=2;i<=n+7;++i)
	{
    	if(!vis[i])//不是目前找到的素数的倍数 
    	    prime[++cnt]=i;//找到素数~ 
    	for(int j=1;j<=cnt&&i*prime[j]<=n+7;++j)
    	{
    	    vis[i*prime[j]]=1;//找到的素数的倍数不访问 
    	    if(i%prime[j]==0) 
    	        break;//关键!!!! 
   		}
   }
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld",&n,&m);
	Prim();
	for(int i=1;i<=m;++i)
	{
		int in;
		scanf("%lld",&in);
		printf("%lldn",prime[in]);
	}
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P5656 【模板】二元一次不定方程 (exgcd)

没话讲,希望以后还能记得怎么做,感觉不太现实,就记住Exgcd能求ax+by=gcd(a,b)的一组特解算了。。。。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,x,y,X,Y;
void Exgcd(int a,int b)
{
	if(!b)
	{
		x=1;
		y=0;
		return;
	}
	Exgcd(b,a%b);
	X=y;
	Y=x-a/b*y;
	x=X;
	y=Y;
}
int Get_gcd(int x,int y)
{
	return y==0?x:Get_gcd(y,x%y);
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	int a,b,c;
	scanf("%lld%lld%lld",&a,&b,&c);
	x=0,y=0;
	Exgcd(a,b);
	int gcd=Get_gcd(a,b);
	if(c%gcd!=0)
		return 0;
	x*=c/gcd,y*=c/gcd;
	int p=b/gcd,q=a/gcd,k=0;
	if(x<0)
		k=ceil((1.0-x)/p),x+=p*k,y-=q*k;
	if(x>=0)
		k=(x-1)/p,x-=p*k,y+=q*k;
	if(y>0)
		printf("%lld %lld %lld %lld %lldn",(y-1)/q+1,x,(y-1)%q+1,x+(y-1)/q*p,y);
	else
		printf("%lld %lldn",x,y+q*((int)ceil((1.0-y)/q)));
	return true;
}
signed main()
{
	scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P3807 【模板】卢卡斯定理/Lucas 定理

记结论算了

寒假集训记录

寒假集训记录

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 100007
#define M 500007
//#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,mod;
int Pow(int x,int y)
{
	int ans=1,cnt=x;
	while(y)
	{
		if(y&1)
			ans*=cnt,ans%=mod;
		cnt*=cnt;
		cnt%=mod; 
		y>>=1;
	}
	return ans%mod;
}
int C(int a,int b)//模mod意义下求组合数 
{
	if(a<b)
		return 0;
	if(b>a-b)	b=a-b;
	int x=1,y=1;
	for(int i=0;i<b;++i)
	{
		x=(x*(a-i))%mod;
		y=(y*(i+1))%mod;
	}
	return x*Pow(y,mod-2)%mod;
}
int Lucas(int a,int b) 
{
	if(b==0)
		return 1;
	return Lucas(a/mod,b/mod)*C(a%mod,b%mod)%mod;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld%lld%lld",&n,&m,&mod);
	printf("%lldn",Lucas(n+m,m));
	return true;
}
signed main()
{
	scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P3389 【模板】高斯消元法

方法一:高斯消元法,消成上三角矩阵

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 107
#define M 500007
//#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,mod;
double g[N][N],ans[N];
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n+1;++j)
			scanf("%lf",&g[i][j]);
	for(int i=1;i<=n;++i)
	{
		int pos=i;
		for(int j=i+1;j<=n;++j)
			if(fabs(g[pos][i])<fabs(g[j][i]))
				pos=j;
		if(fabs(g[pos][i])<1e-7)
		{
			printf("No Solutionn");
			return 1;
		}
		if(pos!=i)
			swap(g[pos],g[i]);
		double div=g[i][i];
		for(int j=i;j<=n+1;++j)//当前方程,前面的未知数已经消去
			g[i][j]/=div;
		for(int j=i+1;j<=n;++j)//下面的所有方程消去当前系数 
		{
			div=g[j][i];
			for(int k=i;k<=n+1;++k)
				g[j][k]-=g[i][k]*div; 
		 } 
	}
	ans[n]=g[n][n+1];
	for(int i=n-1;i;--i)
	{
		ans[i]=g[i][n+1];
		for(int j=i+1;j<=n;++j)
			ans[i]-=g[i][j]*ans[j];
	}//回带求出答案
	for(int i=1;i<=n;++i)
		printf("%.2lfn",ans[i]); 
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


方法二:高斯约旦消元法,消成对角矩阵(可以说类单位矩阵???哈哈哈)

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 107
#define M 500007
//#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,mod;
double g[N][N];
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n+1;++j)
			scanf("%lf",&g[i][j]);
	for(int i=1;i<=n;++i)
	{
		int pos=i;
		for(int j=i+1;j<=n;++j)
			if(fabs(g[pos][i])<fabs(g[j][i]))
				pos=j;
		if(fabs(g[pos][i])<1e-7)
		{
			printf("No Solutionn");
			return 1;
		}
		if(pos!=i)
			swap(g[pos],g[i]);
		for(int j=1;j<=n;++j)//把其他行系数变为0 
		{
			if(i==j)
				continue;
			double tmp=g[j][i]/g[i][i];
			for(int k=i+1;k<=n+1;++k)
				g[j][k]-=g[i][k]*tmp;
		}
	}
	for(int i=1;i<=n;++i)
		printf("%.2lfn",g[i][n+1]/g[i][i]); //除以系数 
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/



P4783 【模板】矩阵求逆

高斯约旦法求矩阵的逆

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m;
int g[N][N];
int Pow(int x,int y)
{
	int ans=1,cnt=x;
	while(y)
	{
		if(y&1)
			ans*=cnt,ans%=mod;
		cnt*=cnt;
		cnt%=mod; 
		y>>=1;
	}
	return ans%mod;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=n;++j)
			scanf("%lld",&g[i][j]);
		g[i][n+i]=1;
	}
	for(int i=1;i<=n;++i)
	{
		int pos=i;
		for(int j=i+1;j<=n;++j)
			if(abs(g[pos][i])<abs(g[j][i]))
				pos=j;
		if(!g[pos][i])
		{
			printf("No Solutionn");
			return 1;
		}
		if(pos!=i)
			swap(g[pos],g[i]);
		int inv=Pow(g[i][i],mod-2);
		for(int j=1;j<=n;++j)//把其他行系数变为0 
		{
			if(i==j)
				continue;
			int tmp=g[j][i]*inv%mod;
			for(int k=i;k<=(n<<1);++k)
				g[j][k]=((g[j][k]-g[i][k]*tmp)%mod+mod)%mod;
		}
		for(int j=1;j<=(n<<1);++j)
			g[i][j]=g[i][j]*inv%mod;
	}
	for(int i=1;i<=n;++i)
	{
		for(int j=n+1;j<=(n<<1);++j)
			printf("%lld ",g[i][j]);
		printf("n");
	}
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,x,y,X,Y;
int a[N],b[N];
void Exgcd(int a,int b)
{
	if(!b)
	{
		x=1;
		y=0;
		return;
	}
	Exgcd(b,a%b);
	X=y;
	Y=x-a/b*y;
	x=X;
	y=Y;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	scanf("%lld",&n);
	int sum=1;
	for(int i=1;i<=n;++i)
		scanf("%lld%lld",&a[i],&b[i]),sum*=a[i];
	int ans=0;
	for(int i=1;i<=n;++i)
	{
		int now=sum/a[i];
		Exgcd(now,a[i]);//求逆元,x是a%b意义下的逆元 
		if(x<0)
			x+=a[i];
		ans+=x*now*b[i];
	}
	printf("%lldn",ans%sum); 
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P3802 小魔女帕琪

推式子

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n; 
int a[N];
bool Solve()
{
 	//freopen("test.in","r",stdin);
	for(int i=1;i<=7;++i)
	{
		scanf("%lld",&a[i]);
		n+=a[i];
	}
	double ans=a[1]*1.0/n*a[2]/(n-1)*a[3]/(n-2)*a[4]/(n-3)*a[5]/(n-4)*a[6]/(n-5)*a[7]*5040;
	printf("%.3lfn",ans); 
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P1072 [NOIP2009 提高组] Hankson 的趣味题

寒假集训记录

收获就是掌握最大公约数和最小公倍数的约束条件吧!

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n; 
int Get_gcd(int x,int y)
{
	return y==0?x:Get_gcd(y,x%y);
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
	int a0,a1,b0,b1;
	scanf("%lld%lld%lld%lld",&a0,&a1,&b0,&b1);
	int ans=0,p=a0/a1,q=b1/b0;
	for(int i=1;i*i<=b1;++i)
		if(b1%i==0)
		{
			if(i%a1==0&&Get_gcd(i/a1,p)==1&&Get_gcd(q,b1/i)==1) 
				++ans;
            int x=b1/i;
            if(x==i) 
				continue; 
            if(x%a1==0&&Get_gcd(x/a1,p)==1&&Get_gcd(q,b1/x)==1) 
				++ans;
		}
	printf("%lldn",ans);
	return true;
}
signed main()
{
	scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


Not Adding

寒假集训记录

一语惊醒梦中人

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1000007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n; 
int a[N];
bool vis[N];
int Get_gcd(int x,int y)
{
	return y==0?x:Get_gcd(y,x%y);
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
 	scanf("%lld",&n);
 	for(int i=1;i<=n;++i)
 	{
 		scanf("%lld",&a[i]);
 		vis[a[i]]=1;
	}
	int ans=0;
	for(int i=1;i<=N-7;++i)
	{
		int gcd=-1;
		if(vis[i])
			continue;
		for(int j=1;j*i<=N-7;++j)
		{
			if(!vis[i*j])
				continue;
			if(gcd==-1)
				gcd=j*i;
			else
				gcd=Get_gcd(gcd,i*j);
		}
		if(gcd==i)
			++ans;
	}
	printf("%lldn",ans);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P2158 [SDOI2008] 仪仗队

寒假集训记录

寒假集训记录

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1000007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,m,k;
int a[N],phi[N],prime[N];
bool vis[N],flag[N];
void Euler(int mxn)
{
	int num=0;
    phi[1]=1;//1要特判 
    for(int i=2;i<=mxn;i++)
    {
        if(flag[i]==0)//这代表i是质数 
        {
            prime[++num]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=num&&prime[j]*i<=mxn;j++)//经典的欧拉筛写法 
        {
            flag[i*prime[j]]=1;//先把这个合数标记掉 
            if (i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];//若prime[j]是i的质因子,则根据计算公式,i已经包括i*prime[j]的所有质因子 
               break;//经典欧拉筛的核心语句,这样能保证每个数只会被自己最小的因子筛掉一次 
            }
            else 
                phi[i*prime[j]]=phi[i]*phi[prime[j]];//利用了欧拉函数是个积性函数的性质 
        }
    }
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
 	scanf("%lld",&n);
 	if(n==1)
 	{
 		printf("0n");
 		return 1;
	 }
 	Euler(n);
 	int ans=0;
 	for(int i=1;i<n;++i)
 		ans+=phi[i];
 	printf("%lldn",ans*2+1);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


Devu and Flowers

容斥+组合数

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1000007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,s;
int inv[N],a[N];
void Get_inv(int mxn)
{
	inv[1]=1;
	for(int i=2;i<=mxn;++i)
		inv[i]=inv[mod%i]*(mod-mod/i)%mod;
}
int C(int y,int x)//模mod意义下求组合数   y在下 
{
	if(y<0||x<0||y<x)
		return 0;
	y%=mod;
	if(y==0||x==0)
		return 1;
	int ans=1;
	for(int i=0;i<x;++i)
		ans=ans*(y-i)%mod;
	for(int i=1;i<=x;++i)
		ans=ans*inv[i]%mod;
	return ans;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
 	scanf("%lld%lld",&n,&s);
 	Get_inv(N-7); 
 	int ans=C(n+s-1,n-1);
 	for(int i=1;i<=n;++i)
 		scanf("%lld",&a[i]);
 	for(int i=1;i<(1<<n);++i)
 	{
 		int tmp=n+s,num=0;
 		for(int j=0;j<n;++j)
 			if(i>>j&1)
 				++num,tmp-=a[j+1];
 		tmp-=num+1;
 		if(num&1)
 			ans=(ans-C(tmp,n-1))%mod;
 		else
 			ans=(ans+C(tmp,n-1))%mod;
	 }
	 printf("%lldn",(ans+mod)%mod);
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


Moamen and XOR

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 200007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
int T=1,n,k;
int fac[N],invfac[N];
int Pow(int x,int y)
{
	int ans=1,cnt=x;
	while(y)
	{
		if(y&1)
			ans*=cnt,ans%=mod;
		cnt*=cnt;
		cnt%=mod;
		y>>=1;
	}
	return ans%mod;
}
int C(int a,int b)
{
	return (fac[a]*invfac[b]%mod)*invfac[a-b]%mod;
}
void Init()
{
	fac[0]=invfac[0]=1;
 	for(int i=1;i<=N-7;++i)
 		fac[i]=1ll*fac[i-1]*i%mod;
 	invfac[N-7]=Pow(fac[N-7],mod-2);
 	for(int i=N-8;i;--i)
 		invfac[i]=1ll*invfac[i+1]*(i+1)%mod;
}
bool Solve()
{
 	//freopen("test.in","r",stdin);
 	scanf("%lld%lld",&n,&k);
 	if(n&1)
 	{
 		int tmp=1;
		for(int i=1;i<=((n+1)>>1);++i)
			tmp=(tmp+C(n,2*i-1))%mod;
		printf("%lldn",Pow(tmp,k));
	}
 	else
 	{
 		int tmp=0,t1=0,t2=0;
 		for(int i=2;i<=n;i+=2)
 			t1=(t1+C(n,i))%mod;
 		for(int i=1;i<=n;i+=2)
 			t2=(t2+C(n,i))%mod;
 		for(int i=1;i<=k;++i)
 			tmp=(tmp+1ll*t2*Pow(t1,k-i)%mod*Pow(Pow(2,i-1),n)%mod)%mod;
		printf("%lldn",(Pow(Pow(2,k),n)-tmp+mod)%mod);
	 }
	return true;
}
signed main()
{
	Init();
	scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


原文链接: https://www.cnblogs.com/yexinqwq/p/17021039.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    寒假集训记录

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/309406

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月16日 上午11:01
下一篇 2023年2月16日 上午11:02

相关推荐