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();}
Everything that kills me makes me feel alive.