铅导体
问题描述 何老板要求第三题要很简单,最好是铅导体的难度。 于是,nodgd把N个铅块用N−1根导线相连,就形成了一个铅导体。只要是在这个基础上出题,就符合何老板的要求。nodgd为了方便,就把其中的一个铅块固定在了墙上,其他铅块在导线的作用下自然下垂。每个铅块有个固定的纯度,若干个相同纯度的铅块可以聚变发电,发电的电压与铅块的数量成正比。每当nodgd需要电疗的时候,就在铅导体上选一个铅块,把它和挂在它下面的所有铅块都取下来,在这当中选一些纯度相同的铅块发电,发电之后将这些铅块挂回原来的位置。nodgd希望电疗的电压越高越好,在电压相同的情况下,nodgd又希望使用纯度更低的铅块。 但是ciocio经常来捣乱,他时不时的把整个铅导体取下来,重新选一个铅块固定到墙上,其他的铅块继续自然下垂。那么问题来了,nodgd每次都想享受最高电压的电疗,需要你大声喊出应该使用多少个纯度是多 少的铅块。
输入格式 输入文件C.in。 第一行四个整数N, A, Q, I,表示铅块的数量、铅块纯度的范围、操作的总次数、测试点编号。 铅块按1 ∼ N编号,一开始nodgd把编号为1的铅块固定在墙上。铅块的纯度是1 ∼ A之间的一个整 数。 接下来N − 1行,每行两个整数u, v,表示有一条导线连接。 接下来一行,N个整数,表示每个铅块的纯度。 接下来Q行,每行输入两个整数op, u。 若op = 1,表示ciocio把整个铅导体取下来,再把编号为u的铅块重新固定在墙上。 若op = 2,表示nodgd把编号为u的铅块以及挂在他下面的所有铅块暂时取下来,选出其中一些铅块进行聚变发电。如果要求该组测试点要求强制在线,设上一次输出的答案两个数分别为lasta和lastb,则u′ = (u+lasta×23 + lastb×233)%N + 1才是真正的节点编号。
输出格式 输出文件C.out。 每次op = 2的时候输出一行,两个整数,分别是使用铅块的纯度和数量。
样例输入 5 3 8 0 1 2 1 3 3 4 3 5 1 1 2 2 3 2 3 2 1 2 5 1 3 2 4 2 2 2 1 2 3
样例输出 2 2 1 2 3 1 2 1 1 1 1 2 1 2
数据范围 
dfs序+分块求众数,很机智的一个做法将新编号对应的纯度数组复制一遍,处理根在子树内就会方便很多。
#include<iostream>#include<cstdio>#include<algorithm>#include<cstdlib>#include<cstring>#include<cmath>#define ll long longusing namespace std;const int base=500;template <typename T>inline void _read(T& x){ char t=getchar();bool sign=true; while(t<'0'||t>'9'){if(t=='-')sign=false;t=getchar();} for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0'; if(!sign)x=-x;}int n,m,q,I,N,S;int tot,e,root;int lasta,lastb;int vistime;struct line{ int from,to; line(){} line(int x,int y){from=x;to=y;}};line edge[200005];int last[100005],_next[200005];void add_edge(int x,int y){ edge[++e]=line(x,y); _next[e]=last[x]; last[x]=e;}int father[100005],dep[100005],p[100005][35],id[100005],R[100005],purity[100005],a[100005];void dfs(int x,int fa){ int i,j,k,v; id[x]=++vistime; dep[x]=dep[fa]+1; father[x]=fa; k=ceil(log(dep[x])/log(2)); p[x][0]=fa; for(i=1;i<=k;i++)p[x][i]=p[p[x][i-1]][i-1]; for(i=last[x];i;i=_next[i]){ v=edge[i].to; if(v==fa)continue; dfs(v,x); } R[x]=vistime;}struct node{ int Purity,sum; node(){} node(int x,int y){Purity=x;sum=y;}};node block[605][1005];int cnt[100005];int all[605][100005];void divide(){ int i,j,k,t1,t2; N=(n<<1); tot=(N-1)/base+1; for(i=1;i<=tot;i++){ int pure=0,sum=0; for(j=i;j<=tot;j++){ int lim=j*base; lim=min(lim,N); for(k=(j-1)*base+1;k<=lim;k++){ t1=a[k]; t2=++cnt[a[k]]; if(t2>sum||(t2==sum&&a[k]<pure)){ sum=cnt[a[k]]; pure=a[k]; } } block[i][j]=node(pure,sum); if(i==1){ for(k=1;k<=m;k++){ all[j][k]=cnt[k]; } } } for(j=1;j<=m;j++)cnt[j]=0; }}int go_up(int x,int step){ int i; for(i=S;i>=0;i--){ if(step&(1<<i))x=p[x][i]; } return x;}void solve(int x){ //cout<<"solve:"<<x<<endl; int l,r,i,j,k; if(x==root){ l=1; r=n; } else if(id[x]<=id[root]&&id[root]<=R[x]){ //cout<<"case1"<<endl; int temp=go_up(root,dep[root]-dep[x]-1); l=R[temp]+1; r=id[temp]-1+n; } else { //cout<<"case2"<<endl; l=id[x];r=R[x]; } int bl,br,tl,tr; bl=(l-2+base)/base+1; br=r/base; tl=(bl-1)*base+1; tr=br*base; //cout<<"l:"<<l<<" r:"<<r<<endl; //cout<<"block("<<bl<<","<<br<<")"<<endl; //cout<<"work["<<l<<","<<r<<"]"<<endl; int pure,sum,t1,t2; if(bl>br){ //cout<<"fuck"<<endl; pure=0;sum=0; for(i=l;i<=r;i++){ t1=++cnt[a[i]]; t2=a[i]; if(t1>sum||(t1==sum&&t2<pure)){ sum=t1;pure=t2; } } //cout<<"cnt[105]:"<<cnt[105]<<endl; for(i=l;i<=r;i++)cnt[a[i]]=0; } else { pure=block[bl][br].Purity; sum=block[bl][br].sum; for(i=l;i<tl;i++){ t1=++cnt[a[i]]+all[br][a[i]]-all[bl-1][a[i]]; t2=a[i]; if(t1>sum||(t1==sum&&t2<pure)){ sum=t1;pure=t2; } } for(i=tr+1;i<=r;i++){ t1=++cnt[a[i]]+all[br][a[i]]-all[bl-1][a[i]]; t2=a[i]; if(t1>sum||(t1==sum&&t2<pure)){ sum=t1;pure=t2; } } for(i=l;i<tl;i++)cnt[a[i]]=0; for(i=tr+1;i<=r;i++)cnt[a[i]]=0; } PRintf("%d %d/n",pure,sum); lasta=pure; lastb=sum;}int main(){ freopen("C.in","r",stdin); freopen("C.out","w",stdout); int i,j,k; cin>>n>>m>>q>>I; S=ceil(log(n)/log(2)); for(i=1;i<n;i++){ int x,y; _read(x);_read(y); add_edge(x,y); add_edge(y,x); } dfs(1,0); /*cout<<"fa:"<<endl; for(i=1;i<=n;i++){ cout<<"i:"<<i<<" "<<p[i][0]<<" "<<p[i][1]<<endl; }*/ for(i=1;i<=n;i++){ _read(purity[i]); a[id[i]]=purity[i]; } for(i=1;i<=n;i++){ a[i+n]=a[i]; } divide(); while(q--){ int op,x; _read(op);_read(x); if(I%2==0)x=(x+lasta*23+lastb*233)%n+1; //cout<<"x:"<<x<<endl; if(op==1){ root=x; } else { solve(x); } }}新闻热点
疑难解答