noip模拟15

T1

恶心的数学题,还卡空间...

于是考虑数组二次调用,用完memset

记录一手二维前缀和对不同询问离线修改,最后一块回答即可

Code



#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
#define pf printf
namespace EMT{
	inline int read(){
		int w = 0 ; bool fg = 0 ; char ch = getchar() ;
		while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
		while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ; 
		return fg ? -w : w ;
	}
	const int N=10011;const int mod=1<<30;
	std::bitset<4010>gc[4010];int a[4010][4010],b[4010][4010],T;struct node{int n,m,ans;}q[N];
	inline void pi(int x){pf("%d",x);}inline void pn(){pf("\n");}
	inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
	inline short main(){
		F(i,1,4000)
			F(j,1,4000)
				if(gc[j][i]||gcd(i,j)==1)
					gc[i][j]=1;
		T=read();
		F(i,1,T)q[i].n=read(),q[i].m=read();
		F(i,1,4000)
			F(j,1,4000){
				a[i][j]=((0ll+a[i-1][j]+a[i][j-1]-a[i-1][j-1]+(gc[i][j]?i*j:0))%mod+mod)%mod;
				b[i][j]=((0ll+b[i-1][j]+b[i][j-1]-b[i-1][j-1]+gc[i][j])%mod+mod)%mod;
			}
		F(i,1,T)
			q[i].ans=((0ll+q[i].ans+a[q[i].n-1][q[i].m-1]%mod-a[q[i].n/2][q[i].m/2]*4%mod)%mod+mod)%mod;
		F(i,1,T)
			q[i].ans=((0ll+q[i].ans+b[q[i].n-1][q[i].m-1]*q[i].n*q[i].m%mod-b[q[i].n/2][q[i].m/2]*q[i].n*q[i].m%mod)%mod+mod)%mod;
		memset(a,0,sizeof(a));memset(b,0,sizeof(b));
		F(i,1,4000)
			F(j,1,4000)
				a[i][j]=((0ll+a[i-1][j]+a[i][j-1]-a[i-1][j-1]+(gc[i][j]?i:0))%mod+mod)%mod,
				b[i][j]=((0ll+b[i-1][j]+b[i][j-1]-b[i-1][j-1]+(gc[i][j]?j:0))%mod+mod)%mod;
		F(i,1,T)
			q[i].ans=((0ll+q[i].ans-a[q[i].n-1][q[i].m-1]*q[i].m%mod-b[q[i].n-1][q[i].m-1]*q[i].n%mod)%mod+mod)%mod;
		F(i,1,T)
			q[i].ans=((0ll+q[i].ans+a[q[i].n/2][q[i].m/2]*2*q[i].m%mod+b[q[i].n/2][q[i].m/2]*2*q[i].n%mod)%mod+mod)%mod;
		F(i,1,T)
			pi((0ll+q[i].ans*2+q[i].n+q[i].m)%mod),pn();
		return 0;
	}
}
signed main(){return EMT::main();}

T2

树剖求lca,按照权值大小排序,每次合并权值大的点,6次分别判断哪个端点最优即可。

Code

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline void db(){pf("debug\n");}
	#define int long long
	typedef long long ll;//(double)clock() / (double)CLOCKS_PER_SEC;
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
	inline void pi(int x){pf("%lld ",x);}inline void pn(){pf("\n");}
	inline void file(){freopen("in.in","r",stdin);}//freopen("my.out","w",stdout);}
	const int N=1e6+100;
	int fa[N],n,co,head[N],l[N],r[N],pre[N],val[N],len[N],ans;struct node{int next,to,w;}e[N<<1];
	struct pt{int id,val;}p[N];struct tree{int top,deep,son,fa,size,dfn;}t[N<<1];
	inline int find(int x){return fa[x]==x?fa[x]:fa[x]=find(fa[x]);}
	inline void add(int x,int y,int z){e[++co].next=head[x],e[co].to=y,e[co].w=z;head[x]=co;}
	inline void clean(){
		co=0;F(i,1,n)head[i]=pre[i]=0;ans=0;
	}
	inline void dfs(int x,int f){
		t[x].son=-1;t[x].size=1;
		for(register int i=head[x],j;i;i=e[i].next){
			j=e[i].to;if(j==f)continue;
			t[j].deep=t[x].deep+1;t[j].fa=x;
			pre[j]=pre[x]+e[i].w;
			dfs(j,x);
			t[x].size+=t[j].size;
			if(t[x].son==-1||t[t[x].son].size<t[j].size)t[x].son=j;
		}
	}
	inline void dfs2(int x,int tp){
		t[x].top=tp;
		if(t[x].son==-1)return;
		dfs2(t[x].son,tp);
		for(register int i=head[x];i;i=e[i].next)
			if(e[i].to!=t[x].son&&e[i].to!=t[x].fa)
				dfs2(e[i].to,e[i].to);
	}
	inline int getlca(int x,int y){
		int tx=t[x].top,ty=t[y].top;
		while(tx!=ty){
			if(t[tx].deep>=t[ty].deep)x=t[tx].fa;
			else y=t[ty].fa;
			tx=t[x].top;ty=t[y].top;
		}
		if(t[x].deep>=t[y].deep)return y;
		return x;
	}
	inline bool cmp(pt a,pt b){return a.val>b.val;}
	inline void merge(int x,int y){
		int lca,maxn=0,keyl,keyr;
		if(maxn<len[x])maxn=len[x],keyl=l[x],keyr=r[x];
		if(maxn<len[y])maxn=len[y],keyl=l[y],keyr=r[y];
		lca=getlca(l[x],l[y]);if(maxn<pre[l[x]]+pre[l[y]]-2*pre[lca])maxn=pre[l[x]]+pre[l[y]]-2*pre[lca],keyl=l[x],keyr=l[y];
		lca=getlca(l[x],r[y]);if(maxn<pre[l[x]]+pre[r[y]]-2*pre[lca])maxn=pre[l[x]]+pre[r[y]]-2*pre[lca],keyl=l[x],keyr=r[y];
		lca=getlca(r[x],l[y]);if(maxn<pre[r[x]]+pre[l[y]]-2*pre[lca])maxn=pre[r[x]]+pre[l[y]]-2*pre[lca],keyl=r[x],keyr=l[y];
		lca=getlca(r[x],r[y]);if(maxn<pre[r[x]]+pre[r[y]]-2*pre[lca])maxn=pre[r[x]]+pre[r[y]]-2*pre[lca],keyl=r[x],keyr=r[y];
		fa[x]=y;l[y]=keyl;r[y]=keyr;len[y]=maxn;
	}
	inline short main(){
		//file();
		int T=read();
		while(T--){
			n=read();
			F(i,1,n)fa[i]=i;
			F(i,1,n)l[i]=r[i]=i,p[i].id=i,p[i].val=val[i]=read(),len[i]=0;
			F(i,1,n-1){
				int x=read(),y=read(),z=read();
				add(x,y,z);add(y,x,z);
			}dfs(1,0);dfs2(1,1);
			std::sort(p+1,p+n+1,cmp);
			F(i,1,n){
				for(register int j=head[p[i].id];j;j=e[j].next){
					if(val[e[j].to]>=val[p[i].id]){
						int x=find(p[i].id),y=find(e[j].to);
						if(x==y)continue;
						merge(x,y);ans=max(ans,val[p[i].id]*len[y]);
					}
				}
			}
			pi(ans);pn();
			clean();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

T3

神仙线段树...

\(l,r,mid,p\)表示区间最左、最右端的花精位置、中间最长的两边距离、中间最长的两边距离的中点。

分情况讨论的up是真的妙...

Code



#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	typedef long long ll;//(double)clock() / (double)CLOCKS_PER_SEC;
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
	int n,m;const int N=2e5+100;
	struct tree{int l,r,mid,p;}t[N<<2];
	inline void up(int p){
		int l=p<<1,r=p<<1|1;
		if(!t[l].l)t[p]=t[r];
		else if(!t[r].l)t[p]=t[l];
		else{
			t[p].l=t[l].l,t[p].r=t[r].r;
			int len1=t[l].mid,len2=t[r].mid;
			if(len1>=len2){
				t[p].mid=t[l].mid;
				t[p].p=t[l].p;
			}else t[p].mid=t[r].mid,t[p].p=t[r].p;
			int len=t[r].l-t[l].r-1;len=len/2-((len&1)?0:1)+1;
			if(len>t[p].mid)t[p].p=t[l].r+len,t[p].mid=len;
			else if(len==t[p].mid)t[p].p=min(t[p].p,t[l].r+len);			
		}
	}
	inline void change(int p,int l,int r,int opt,int v){
		if(l==r){
			if(opt)t[p].l=t[p].r=l;
			else t[p].l=t[p].r=0;
			t[p].mid=t[p].p=0;
			return;
		}
		int mid=(l+r)>>1;
		if(v<=mid)change(p<<1,l,mid,opt,v);
		else change(p<<1|1,mid+1,r,opt,v);
		up(p);
	}
	int co,plc[1000100];
	inline short main(){
		n=read(),m=read();
		F(i,1,m){
			int opt=read(),x=read();
			if(opt==1){
				if(!co){co++;plc[x]=1;pi(1);pn();change(1,1,n,1,1);continue;}
				++co;
				int maxn=0,p=0;
				if(t[1].l-1>=n-t[1].r)maxn=t[1].l-1,p=1;
				else maxn=n-t[1].r,p=n;
				if(maxn<t[1].mid){
					maxn=t[1].mid;
					p=t[1].p;
				}
				else if(maxn==t[1].mid)
					p=min(p,t[1].p);
				plc[x]=p;pi(p);pn();
				change(1,1,n,1,p);
			}else change(1,1,n,0,plc[x]),--co;
		}
		return 0;
	}
}
signed main(){return EMT::main();}

posted @ 2021-07-16 14:46  letitdown  阅读(41)  评论(0编辑  收藏  举报