Petrozavodsk Summer-2016. Ural FU Dandelion Contest

A. Square Function

留坑。

 

B. Guess by Remainder

询问$lcm(1,2,3,...,n)-1$即可一步猜出数。

计算$lcm$采用分治FFT即可,时间复杂度$O(n\log^2n)$。

 

C. Subtract if Greater!

对于每个修改操作,$[1,x]$的数无需修改,$[x+1,2x]$的数会减小至少一半,暴力修改即可,$[2x+1,inf]$的数减小之后排名不变,故可以在平衡树上打标记实现。

时间复杂度$O(n\log^2n+m\log n)$。

#include
#include
const int N=100010,inf=~0U>>1;
int n,m,i,op,k,a[N],val[N],tag[N],size[N],son[N][2],f[N],tot,root;
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void add1(int x,int p){
  if(!x)return;
  val[x]+=p;
  tag[x]+=p;
}
inline void pb(int x){
  if(tag[x]){
    add1(son[x][0],tag[x]);
    add1(son[x][1],tag[x]);
    tag[x]=0;
  }
}
inline void up(int x){
  size[x]=1;
  if(son[x][0])size[x]+=size[son[x][0]];
  if(son[x][1])size[x]+=size[son[x][1]];
}
inline void rotate(int x){
  int y=f[x],w=son[y][1]==x;
  son[y][w]=son[x][w^1];
  if(son[x][w^1])f[son[x][w^1]]=y;
  if(f[y]){
    int z=f[y];
    if(son[z][0]==y)son[z][0]=x;
    if(son[z][1]==y)son[z][1]=x;
  }
  f[x]=f[y];son[x][w^1]=y;f[y]=x;up(y);
}
inline void splay(int x,int w){
  int s=1,i=x,y;a[1]=x;
  while(f[i])a[++s]=i=f[i];
  while(s)pb(a[s--]);
  while(f[x]!=w){
    y=f[x];
    if(f[y]!=w){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
    rotate(x);
  }
  if(!w)root=x;
  up(x);
}
int build(int l,int r,int fa){
  int x=++tot,mid=(l+r)>>1;
  f[x]=fa;val[x]=a[mid];
  if(lmid)son[x][1]=build(mid+1,r,x);
  up(x);
  return x;
}
inline void ask(int k){
  int x=root,t;
  while(x){
    pb(x);
    if(val[x]>k)t=x,x=son[x][0];else x=son[x][1];
  }
  splay(t,0);
}
void ins(int&x,int y,int fa){
  if(!x){
    x=y;
    f[y]=fa;
    return;
  }
  pb(x);
  size[x]++;
  if(val[y]

  

D. Eastern Subregional

留坑。

 

E. K-transform

DP显然,快速幂+FFT优化即可。时间复杂度$O(k\log k\log m)$。

 

F. Suffix Array for Thue-Morse

留坑。

 

G. XOR Tree

求出路径上偶数的集合然后分类讨论即可。

#include 
using namespace std ;

typedef long long LL ;

const int MAXN = 100005 ;
const int MAXE = 200005 ;

struct Edge {
    int v , n ;
    Edge () {}
    Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} ;

Edge E[MAXE] ;
int H[MAXN] , cntE ;
int dep[MAXN] ;
int top[MAXN] ;
int siz[MAXN] ;
int son[MAXN] ;
int pre[MAXN] ;
int pos[MAXN] ;
LL val[MAXN] ;
LL sum[MAXN] ;
int precol[MAXN] ;
int even[MAXN] ;
int tree_idx ;
int n , q ;
int eu[MAXN] , ev[MAXN] , ec[MAXN] ;
vector < int > G ;
LL all ;

void init () {
    cntE = 0 ;
    tree_idx = 0 ;
    memset ( H , -1 , sizeof H ) ;
    memset ( val , 0 , sizeof val ) ;
    memset ( sum , 0 , sizeof sum ) ;
    memset ( even , 0 , sizeof even ) ;
}

void addedge ( int u , int v ) {
    E[cntE] = Edge ( v , H[u] ) ;
    H[u] = cntE ++ ;
}

void dfs ( int u ) {
    son[u] = 0 ;
    siz[u] = 1 ;
    for ( int i = H[u] ; ~i ; i = E[i].n ) {
        int v = E[i].v ;
        if ( v == pre[u] ) continue ;
        dep[v] = dep[u] + 1 ;
        pre[v] = u ;
        dfs ( v ) ;
        siz[u] += siz[v] ;
        if ( siz[son[u]] < siz[v] ) son[u] = v ;
    }
}

void rebuild ( int u , int top_element ) {
    top[u] = top_element ;
    pos[u] = ++ tree_idx ;
    if ( son[u] ) rebuild ( son[u] , top_element ) ;
    for ( int i = H[u] ; ~i ; i = E[i].n ) {
        int v = E[i].v ;
        if ( v == pre[u] || v == son[u] ) continue ;
        rebuild ( v , v ) ;
    }
}

void dfs2 ( int u , int it ) {
    precol[u] = it ;
    for ( int i = H[u] ; ~i ; i = E[i].n ) {
        int v = E[i].v ;
        if ( v == pre[u] ) continue ;
        dfs2 ( v , val[u] % 2 ? it : u ) ;
    }
}

void geteven ( int u , int lca ) {
  //printf("geteven %d %d\n",u,lca);
    while ( dep[u] > dep[lca] ) {
      //printf("  %d %d %d\n",u,val[u],precol[u]);
        if ( val[u] % 2 == 0 ) {
          G.push_back ( val[u] ) ;
        }
        u = precol[u] ;
    }
}

void deal ( int u , int v ) {
    LL tot = 0 , num = 0 ;
    int x = u , y = v ;
    //return;
    while ( top[u] != top[v] ) {
        if ( dep[top[u]] < dep[top[v]] ) swap ( u , v ) ;
        num += even[pos[u]] - even[pos[top[u]] - 1] ;
        tot += sum[pos[u]] - sum[pos[top[u]] - 1] ;
        u = pre[top[u]] ;
    }
    //return;
    if ( dep[u] > dep[v] ) swap ( u , v ) ;
    num += even[pos[v]] - even[pos[u]] ;
    tot += sum[pos[v]] - sum[pos[u]] ;
    if ( num == 0 ) {
        printf ( "1\n" ) ;
        return ;
    }
    if ( num >= 3 ) {
        printf ( "2\n" ) ;
        return ;
    }
    G.clear () ;
    geteven ( x , u ) ;
    geteven ( y , u ) ;
    int dis = dep[x] + dep[y] - 2 * dep[u] ;
    sort ( G.begin () , G.end () ) ;
    dis -= ( int ) G.size () ;
    int out = ( all - tot ) & 1 ;
    
    
   // printf("->%d\n",G.size());
    //return;
    
    if ( num == 1 ) {
        if ( G[0] >= dis ) {
            printf ( "1\n" ) ;
            return ;
        } else {
            printf ( "2\n" ) ;
            return ;
        }
    }
    //return;
    if ( num == 2 ) {
        G[0] -= dis - 1 ;
        if ( G[0] <= 1 ) {
            printf ( "2\n" ) ;
            return ;
        } else {
            G[0] %= 2 ;
            if ( ( G[0] == 0 ) ^ ( out == 0 ) ) printf ( "2\n" ) ;
            else printf ( "1\n" ) ;
            return ;
        }
    }
}

void solve () {
    init () ;
    all = 0 ;
    for ( int i = 1 ; i < n ; ++ i ) {
        scanf ( "%d%d%d" , &eu[i] , &ev[i] , &ec[i] ) ;
        addedge ( eu[i] , ev[i] ) ;
        addedge ( ev[i] , eu[i] ) ;
        all += ec[i] ;
    }
    dfs ( 1 ) ;
    rebuild ( 1 , 1 ) ;
    for ( int i = 1 ; i < n ; ++ i ) {
        if ( dep[eu[i]] > dep[ev[i]] ) {
            sum[pos[eu[i]]] = ec[i] ;
            val[eu[i]] = ec[i] ;
            even[pos[eu[i]]] = ec[i] % 2 == 0 ;
        } else {
            sum[pos[ev[i]]] = ec[i] ;
            val[ev[i]] = ec[i] ;
            even[pos[ev[i]]] = ec[i] % 2 == 0 ;
        }
    }
    dfs2 ( 1 , 0 ) ;
    for ( int i = 2 ; i <= n ; ++ i ) {
        sum[i] += sum[i - 1] ;
        even[i] += even[i - 1] ;
    }
    while ( q -- ) {
        int u , v ;
        scanf ( "%d%d" , &u , &v ) ;
        deal ( u , v ) ;
    }
}

int main () {
    while ( ~scanf ( "%d%d" , &n , &q ) ) solve () ;
    return 0 ;
}

  

H. Fence

留坑。

 

I. Friends and Berries - 2

首先求出凸包,然后分治求出每个点的最远点,检查一下直径是否合法,是的话那么所有直径都是答案。时间复杂度$O(n\log n)$。

#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef pairPI;
const int N=500010;
int n,i,f[N];ll d[N];
mapidx;
setans;
struct P{
  int x,y;
  P(){x=y=0;}
  P(int _x,int _y){x=_x,y=_y;}
  void input(){scanf("%d%d",&x,&y);}
  bool operator<(const P&p)const{
    if(x!=p.x)return x=x+n)return -t;
  return t;
}
inline ll vect(P p,P p1,P p2){
  return 1LL*(p1.x-p.x)*(p2.y-p.y)-1LL*(p1.y-p.y)*(p2.x-p.x);
}
int convexhull(P*p,int n,P*q){
  int i,k,m;
  sort(p,p+n);
  m=0;
  for(i=0;i1&&vect(q[m-2],q[m-1],p[i])<0)m--;
  k=m;
  for(i=n-2;i>=0;q[m++]=p[i--])while(m>k&&vect(q[m-2],q[m-1],p[i])<0)m--;
  return --m;
}
void solve(int l,int r,int dl,int dr){
  int m=(l+r)>>1;
  f[m]=dl;
  d[m]=cal(m,dl);
  for(int i=dl+1;i<=dr;i++){
    ll t=cal(m,i);
    if(t>d[m])d[m]=t,f[m]=i;
  }
  if(lm)solve(m+1,r,f[m],dr);
}
inline bool check(P A,P B){
  for(int i=0;iy)swap(x,y);
  ans.insert(PI(x,y));
}
int main(){
  scanf("%d",&n);
  for(i=0;id[x])x=i;
  for(i=0;i::iterator it=ans.begin();it!=ans.end();it++){
    //printf("%d %d\n",it->first,it->second);
    printf("%d %d\n",idx[PI(b[it->first].x,b[it->first].y)],
                     idx[PI(b[it->second].x,b[it->second].y)]);
  }
}

  

J. Oleg and Cola

超图上的最短路,dijkstra+染色即可。时间复杂度$O(m\log m)$。

#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef pairP;
typedef pairPI;
const int N=200010;
int n,m,i,ce,id[N],st[N][2],en[N][2];
int cnt,fin[N*2];
P pos;ll ans;
bool v[N][2];
ll d[N][2];
P pre[N][2];
priority_queue,greater >q;
struct E{
  int u,v,len,light;
  E(){}
  E(int _u,int _v,int _len,int _light){u=_u,v=_v,len=_len,light=_light;}
}e[N];
inline bool cmp(int x,int y){
  if(e[x].u!=e[y].u)return e[x].u1;i--)st[e[id[i]].u][0]=i;
  for(i=1;i<=n;i++)st[i][1]=st[i][0],en[i][1]=en[i][0];
  for(i=2;i<=ce;i++)if(e[i].u==1)ext(i,0,0,P(0,0));
  while(!q.empty()){
    PI t=q.top();q.pop();
    int x=t.second.first,y=t.second.second;
    ll z=t.first;
    int o=e[x].v;
    while(st[o][y]<=en[o][y]){
      int i=id[en[o][y]];
      if(e[i].light

  

K. Process with Constant Sum

留坑。

你可能感兴趣的:(Petrozavodsk Summer-2016. Ural FU Dandelion Contest)