NOIP模拟day2 2020.10.16

共四道题,只做了三道,T4弃了。其实还有day1的,不过因为其他人考day1时我在上文化课,感觉day1题也没啥想写的,就只把T3那个跟去年csp-jT4差不多的边权为一奇偶最短路贴个吧

#include<bits/stdc++.h>
using namespace std;
const int N=5010;
const int inf=0x7fffffff;
int tot1,tot2,first1[N],Next1[N*2],to1[N*2],first2[N],Next2[200010],to2[200010],w[200010],ans[100010],dis[N][2],id[200010];
int n,m,t,x,y,z;
int Read()
{
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch))
	{
		x=(x<<1)+(x<<3)+ch-'0';
		ch=getchar();
	}
	return f*x;
}
void add1(int a,int b)
{
	tot1++;
	Next1[tot1]=first1[a];
	first1[a]=tot1;
	to1[tot1]=b;
}
void add2(int a,int b,int c,int d)
{
	tot2++;
	Next2[tot2]=first2[a];
	first2[a]=tot2;
	to2[tot2]=b;
	w[tot2]=c;
	id[tot2]=d;
}
void bfs(int st)
{
	if(st==2)
	{
		int x=0;
	}
	for(int i=1;i<=n;i++) dis[i][0]=dis[i][1]=inf;
	dis[st][0]=0;
	queue<pair<int,int> >q;
	q.push(make_pair(st,0));
	while(q.size())
	{
		int u=q.front().first;
		int f=q.front().second;
		q.pop();
		for(int i=first1[u];i;i=Next1[i])
		{
			int v=to1[i];
			if(dis[v][f^1]==inf)
			{
				dis[v][f^1]=dis[u][f]+1;
				q.push(make_pair(v,f^1));
			}
		}
	}
}
int main()
{
	n=Read(),m=Read(),t=Read();
	for(int i=1;i<=m;i++) x=Read(),y=Read(),add1(x,y),add1(y,x);
	for(int i=1;i<=t;i++)
    {
    	x=Read(),y=Read(),z=Read();
    	add2(x,y,z,i);
    }
    for(int u=1;u<=n;u++)
    {
    	bfs(u);
    //	cout<<u<<endl;
   // 	for(int i=1;i<=n;i++) cout<<dis[i][0]<<" "<<dis[i][1]<<endl;
    	for(int i=first2[u];i;i=Next2[i])
    	{
    		int tot=0,whe=0;
    		for(int j=first1[u];j;j=Next1[j])
    		{
    			tot++;
    			if(tot){
    				whe=1;
    				break;
    			}
     		}
     		if(!whe&&w[i])
     		{
     			ans[id[i]]=0;
     			continue;
     		}
     		
    		int v=to2[i];
    		int f=w[i]%2;
    		if(v==u&&w[i]==0)
    		{
    			ans[id[i]]=1;
    			continue;
    		}
    		if(dis[v][f]!=inf&&dis[v][f]<=w[i]) ans[id[i]]=1;
    	}
    }
    for(int i=1;i<=t;i++) if(ans[i]) printf("Yes\n");
    else printf("No\n");
}
//8 7 4 1 2 2 3 3 4 5 6 6 7 7 8 8 5 2 3 1 1 4 1 5 5 8 1 8 10

好,说day2的题吧,T1很简单,发现每次修改密度或体积对答案影响是只用加减一个对应的体积或密度,然后二分查找,O(1)修改位置,O(1)修改答案,总复杂度是nlog的,能过。
code:

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int n,m,saber,a[N],b[N],c[N],d[N],x,delta;
long long Max,Min;
int Read()
{
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch))
	{
		x=(x<<1)+(x<<3)+ch-'0';
		ch=getchar();
	}
	return f*x;
}
void Do(int *a,int *b,int val,int add)
{
	if(add==1)
	{
		int pos=upper_bound(a+1,a+1+n,val)-a-1;
		a[pos]++;
		Max+=b[pos],Min+=b[n-pos+1];
	}
	else
	{
		int pos=lower_bound(a+1,a+1+n,val)-a;
		a[pos]--;
		Max-=b[pos],Min-=b[n-pos+1];
	}
}
int main()
{
	n=Read(),m=Read();
	for(int i=1;i<=n;i++) a[i]=Read(),c[i]=a[i];
	for(int i=1;i<=n;i++) b[i]=Read(),d[i]=b[i];
	sort(c+1,c+1+n),sort(d+1,d+1+n);
	for(int i=1;i<=n;i++) Max+=(long long)c[i]*d[i],Min+=(long long)c[i]*d[n-i+1];
	cout<<Min<<" "<<Max<<endl;
	for(int i=1;i<=m;i++)
	{
		saber=Read(),x=Read(),delta=Read();
		if(saber==1) Do(c,d,a[x],delta),a[x]+=delta;
		else Do(d,c,b[x],delta),b[x]+=delta;
		printf("%lld %lld\n",Min,Max);
	}
	return 0;
	
}

T2的话是思维题,直接贴题解了:
先求出所有颜神最终所在的位置集合。初始状态坐标最小的颜神编号为1。在行走过程中,若有一个颜神从0走到L−1,那么坐标最小的颜神的编号就会加1。若有一个颜神从L−1走到0,坐标最小的颜神的编号就会减1。这样就可以得到最终位置的坐标最小的是哪一个颜神了。
时间复杂度O(n)。期望得分:100.
就是处理尾到首和首到尾有点恶心…
code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,L,T,sj,st[N],tot,x,y,ref[N];
struct asd
{
	int zhi;
	int id;
}a[N];
bool comp(asd a,asd b)
{
	return a.zhi<b.zhi;
}
int Read()
{
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch))
	{
		x=(x<<1)+(x<<3)+ch-'0';
		ch=getchar();
	}
	return f*x;
}
int jia(int x,int v) {return (x+v)%L;}
int jian(int x,int v)
{
	if(x>=v) return x-v;
	return L-v+x;
}
int Jia(int x,int v){
if(x+v<=n) return x+v;
else return x+v-n;
}
int Jian(int x,int v)
{
	if(x-v>=1) return x-v;
	return n-v+x;
}
int main()
{
	n=Read(),L=Read(),T=Read();
	sj=T%L;
	for(int i=1;i<=n;i++)
	{
		x=Read(),y=Read();
		a[i].zhi=x,a[i].id=i;
		if(y==1)
		{
			st[i]=jia(x,sj);
			if(x+sj>=L) tot++; 
		}
		else
		{
			st[i]=jian(x,sj);
			if(x<sj) tot--;
		}
	}
	sort(a+1,a+1+n,comp);
	sort(st+1,st+1+n);
	for(int i=1;i<=n;i++)
	{
		if(tot>=0)
		ref[a[i].id]=Jia(i,tot);
		else ref[a[i].id]=Jian(i,-tot);
	}
	for(int i=1;i<=n;i++) printf("%d\n",st[ref[i]]);
	return 0;
}

T3一眼dp题,然后一眼不会。至于dp方程怎么来的,题解还是蛮清楚的(主要懒…)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
code:
(在那%半天都错的,所以直接define int longlong了…)

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,p,ans,f[4010][4010];
signed main()
{
	cin>>n>>p;
	f[0][0]=1;
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=(f[i][j-1]*2%p+f[i-1][j-1]*j%p)%p;
	for(int i=1;i<=n;i++) ans=(ans+f[i][n]*f[i][n]%p)%p,ans=(ans+f[i][n]*f[i-1][n]%p)%p;
	ans=(ans*2)%p;
	cout<<ans;
	return 0;
}
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页