codeforces 1137D & 1137E & 1137F
- D
分成三组(A,B,C)然后先{A,B} , {A} k次直到A,B相遇
发现k%c=0,且k<t+c(否则都可以减c)然后发现A,B到目标需要a*c+c+t-k 次,C需要t次,于是你直接走直到两个相遇就一定是目标点了。
代码
#include<bits/stdc++.h>
using namespace std;
int group[20];
inline void Move(vector<int> S){
printf("next ");
for(size_t i=0;i<S.size();i++){
printf("%d ",S[i]);
}puts("");
fflush(stdout);
int t;scanf("%d",&t);
for(int T=1;T<=t;T++){
char x=0;
while(x<'0'||x>'9')x=getchar();
while(x>='0'&&x<='9')group[x-'0']=T,x=getchar();
}
}
int a[]= {0,1,2,3,4,5,6,7,8,9};
vector<int> fast(1,0),slow(1,1),others(a+2,a+10);
vector<int> total(a,a+2),all(a,a+10);
int main()
{
// cout<<fast[0]<<" "<<slow[0]<<" "<<total[0]<<endl;
while(true){
Move(total);
Move(fast);
if(group[1]==group[0])break;
}
while(true){
Move(all);
if(group[1]==group[2])break;
}
puts("done");
}
- E
因为后面一定比前面加的多,可以直接维护一个类似凸包的东西,每次向后加一个,加前面相当于清空,就线性了。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+5;
ll totlen=1;int m;
struct data{
ll id,b,s;
data(ll id=0):id(id),b(0),s(0){}
}t[N];
int top=1;
ll calcsum(int i){
ll b=i==top?t[i].b:t[i].b+t[i+1].b;
ll s=i==top?t[i].s:t[i].s+t[i+1].s;
return b+(ll)(t[i].id-1ll)*s;
}
int main()
{
cin>>totlen>>m;
t[1]=data(1);
while(m--){
int opt=0;scanf("%d",&opt);
if(opt==1){
ll sum;
scanf("%lld",&sum);
totlen+=sum;
t[top=1]=data(1);
}else if(opt==2){
ll sum;
scanf("%lld",&sum);
while(top>1){
ll T1=calcsum(top);
ll T2=calcsum(top-1);
ll sub1=totlen+1ll-t[top].id;
ll sub2=totlen+1ll-t[top-1].id;
if((long double)T1*sub2 >= (long double)T2*sub1){
t[top-1].b+=t[top].b;
t[top-1].s+=t[top].s;
--top;
}else break;
}
t[++top]=data(totlen+1);
totlen+=sum;
// cout<<"!"<<endl;
// cout<<calcsum(top)<<endl;
}else{
ll b,s;
scanf("%lld%lld",&b,&s);
t[top].b+=b;
t[top].s+=s;
}
while(top>1){
ll T=calcsum(top),T2=calcsum(top-1);
if(T>=T2){
t[top-1].b+=t[top].b;
t[top-1].s+=t[top].s;
--top;
}else break;
}
// cout<<calcsum(top-1)<<endl;
// for(int i=1;i<=top;i++)cout<<t[i].id<<" , ";puts("");
printf("%lld %lld\n",t[top].id,calcsum(top));
}
}
- F
因为无论如何都有两个叶子节点,那最大的一定是最后一个,然后每次就相当于是把之前最大的和新的最大的这条链的点全部提到最后面。发现这个非常像LCT的换根操作,在access的时候维护一下每个段的长度就行了
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,T;
struct Splay{
int ch[2],fa;bool rev;
int col,paint,sz;
}t[N];
int cnt,null=0;
inline bool isroot(int x){return t[t[x].fa].ch[1]!=x&&t[t[x].fa].ch[0]!=x;}
inline bool son(int x){return t[t[x].fa].ch[1]==x;}
inline void pushup(int x){t[x].sz=t[t[x].ch[1]].sz+t[t[x].ch[0]].sz+1;}
inline void pushdown(int x){
if(t[x].rev){
swap(t[x].ch[0],t[x].ch[1]);
if(t[x].ch[0])t[t[x].ch[0]].rev^=1;
if(t[x].ch[1])t[t[x].ch[1]].rev^=1;
t[x].rev=0;
}
if(t[x].paint){
t[x].col=t[x].paint;
if(t[x].ch[1])t[t[x].ch[1]].paint=t[x].paint;
if(t[x].ch[0])t[t[x].ch[0]].paint=t[x].paint;
t[x].paint=0;
}
}
inline void pushnow(int x){
if(!isroot(x))pushnow(t[x].fa);
pushdown(x);
}
inline void rotate(int x){
int f=t[x].fa,g=t[t[x].fa].fa;
bool a=son(x),b=son(x)^1;
if(!isroot(f))t[g].ch[son(f)]=x;
t[x].fa=g;
t[t[x].ch[b]].fa=f;t[f].ch[a]=t[x].ch[b];
t[x].ch[b]=f;t[f].fa=x;
pushup(f);pushup(x);
}
inline void splay(int x){
pushnow(x);
while(!isroot(x)){
int f=t[x].fa;
if(!isroot(f)){
if(son(x)^son(f))rotate(x);
else rotate(f);
}
rotate(x);
}
}
#define lowbit(x) (x&(-x))
struct fenwick{
int t[N<<1],n;
void set(int _n){n=_n;}
inline void add(int x,int y){
for(;x<=n;x+=lowbit(x))t[x]+=y;
}
inline int qry(int x){
int ans=0;for(;x;x-=lowbit(x))ans+=t[x];
return ans;
}
}BIT;
inline void access(int x,int id){//and make root
int tmp=null;
int d=x;
while(x){
splay(x);
t[x].ch[1]=tmp;
pushup(x);
int SZ=t[x].sz-t[t[x].ch[1]].sz;
BIT.add(t[x].col,-SZ);
//
BIT.add(id,SZ);
tmp=x; x=t[x].fa;
}
splay(d);
t[d].paint=id;
t[d].rev^=1;
}
int anc[N][20];
int hed[N],to[N<<1],nxt[N<<1],ecnt,deg[N];
int dep[N];
inline void adde(int u,int v){
++ecnt;to[ecnt]=v,nxt[ecnt]=hed[u];hed[u]=ecnt;
}
inline void dfs(int x,int pre){
dep[x]=dep[pre]+1;
t[x].fa=pre; anc[x][0]=pre; for(int i=1;1<<i<=n;i++)anc[x][i]=anc[anc[x][i-1]][i-1];
for(int i=hed[x];i;i=nxt[i]){
int v=to[i];if(v==pre)continue;
deg[x]++;
dfs(v,x);
}
}
priority_queue<int,vector<int>,greater<int> > heap;
inline int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=18;~i;i--)if(dep[anc[x][i]]>=dep[y])x=anc[x][i];
if(x==y)return x;
for(int i=18;~i;i--)if(anc[x][i]^anc[y][i]) x=anc[x][i],y=anc[y][i];
return anc[x][0];
}
int start[N<<1];
char opt[20];
inline int qry(int x){
splay(x);
int sd=BIT.qry(t[x].col-1);
int ca=lca(start[t[x].col],x);
int len=dep[start[t[x].col]]+dep[x]-dep[ca]*2+1;
return sd+len;
}
int main()
{
cin>>n>>T;
BIT.set(n+T+1);
for(int i=1;i<n;i++){
int u,v;scanf("%d%d",&u,&v);
adde(u,v);adde(v,u);
}
dfs(n,0);
for(int i=1;i<=n;i++)if(deg[i]==0)heap.push(i);
int time=0;
while(!heap.empty()){
int u=heap.top();heap.pop();
//cout<<u<<endl;
t[u].col=++time;
t[u].sz=1;
BIT.add(time,1);
deg[anc[u][0]]--;
start[time]=u;
if(u!=n&&!deg[anc[u][0]])heap.push(anc[u][0]);
}
int final=n;
while(T--){
scanf("%s",opt+1);
if(opt[1]=='u'){//up
start[++time]=final;
int id;scanf("%d",&id);
final=id;
access(id,time);
}
else if(opt[1]=='c'){//compare
int x,y;scanf("%d%d",&x,&y);
printf("%d\n",qry(x)<qry(y)?x:y);
}
else {//when
int x;scanf("%d",&x);
printf("%d\n",qry(x));
}
}
}