XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Khamovniki

A. Ability Draft

记忆化搜索。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() {  }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n, m, S, g;
int f[100][1<<10];
int p[100];
int s[100][10];

int sm, bg;
int smp, bgp;
int smk[100];
int bgk[100];
int cal(int o, int sta)
{
	if(o > g)return 0;
	if(~f[o][sta])return f[o][sta];
	int x = p[o];
	int y = p[o + 1];
	f[o][sta] = -2e9;

	int canbig = ((sta >> x & 1) == 0);
	int cansml = S - (s[o - 1][x] - (canbig == 0)); //canbig == 0 means we picked ulti

	int sgn = (x / n == y / n) ? 1 : -1;
	if(canbig)
	{
		int add = bgk[++bgp];
		f[o][sta] = max(sgn * cal(o + 1, sta | 1 << x) + add, f[o][sta]);
		--bgp;
	}
	if(cansml)
	{
		int add = smk[++smp];
		f[o][sta] = max(sgn * cal(o + 1, sta) + add, f[o][sta]);
		--smp;
	}
	return f[o][sta];
}
int main()
{
	while(~scanf("%d%d",&n, &S))
	{
		m = n * 2;
		g = m * (S + 1);
		for(int i = 1; i <= g; ++i)
		{
			scanf("%d", &p[i]); --p[i];
			for(int j = 0; j < m; ++j)
			{
				s[i][j] = s[i - 1][j] + (j == p[i]);
			}
		}
		scanf("%d", &sm);
		for(int i = 1; i <= sm; ++i)scanf("%d", &smk[i]);
		sort(smk + 1, smk + sm + 1);
		reverse(smk + 1, smk + sm + 1);
		scanf("%d", &bg);
		for(int i = 1; i <= bg; ++i)scanf("%d", &bgk[i]);
		sort(bgk + 1, bgk + bg + 1);
		reverse(bgk + 1, bgk + bg + 1);

		smp = bgp = 0;
		MS(f, -1);
		printf("%d\n", cal(1, 0)*((p[1]/n==0)?1:-1));
	}
	return 0;
}

/*
【trick&&吐槽】
1 1
1 2 2 1
2
5 3
2
7 2

1 2
2 1 1 2 2 1
4
4 8 8 9
2
6 7
(ans = 2)

2 1
1 3 4 2 2 4 3 1
6
1 4 4 8 9 11
5
14 11 10 8 5

【题意】

【分析】

【时间复杂度&&优化】

*/

  

B. Short Random Problem

留坑。

C. Block, Stock and Two Smoking Galaxy Notes

枚举领导者$S$,它需要满足度数至少为$\frac{n}{2}$。

枚举完领导后,将和$S$认识和不认识的分成两组二分图匹配即可。

时间复杂度$O(m^2)$。

#include<cstdio>
#include<cstdlib>
using namespace std;
const int N=1010,M=10010;
int n,m,i,e[M][2],g[N],v[M],nxt[M],ed,f[N],b[N],T,right[N],deg[N];
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
bool find(int x){
	for(int i=g[x];i;i=nxt[i])if(b[v[i]]<T){
		b[v[i]]=T;
		if(!f[v[i]]||find(f[v[i]]))return f[v[i]]=x,1;
	}
	return 0;
}
void solve(int S){
	int i;
	for(i=1;i<=n;i++)right[i]=g[i]=0;
	ed=0;
	for(i=1;i<=m;i++){
		if(e[i][0]==S)right[e[i][1]]=1;
		if(e[i][1]==S)right[e[i][0]]=1;
	}
	for(i=1;i<=m;i++){
		if(e[i][0]!=S&&!right[e[i][0]]&&right[e[i][1]])add(e[i][0],e[i][1]);
		if(e[i][1]!=S&&!right[e[i][1]]&&right[e[i][0]])add(e[i][1],e[i][0]);
	}
	for(i=1;i<=n;i++)f[i]=b[i]=0;
	T=0;
	for(i=1;i<=n;i++){
		if(right[i]||i==S)continue;
		T++;
		if(!find(i))return;
	}
	puts("Yes");
	int cnt=0;
	for(i=1;i<=n;i++)if(right[i])cnt++;
	printf("%d %d\n",S,cnt);
	for(i=1;i<=n;i++)if(right[i]){
		printf("%d ",i);
		if(!f[i])f[i]=-1;
		printf("%d\n",f[i]);
	}
	exit(0);
}
int main(){
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++)scanf("%d%d",&e[i][0],&e[i][1]),deg[e[i][0]]++,deg[e[i][1]]++;
	for(i=1;i<=n;i++)if(deg[i]>=n/2-5)solve(i);
	puts("No");
}
/*
5 4
1 2
2 3
3 4
4 5
*/

  

D. Lunch Queue

用一棵平衡树$S$维护整个队列,再对每个队伍用一棵平衡树$T_i$维护。

那么对于新来的一个人,先在$S$中找出满足距离限制最紧的那个点$x$,再在$T_{c_i}$中查找$x$之后最靠前的点作为插队位置。

瓶颈在于最后一步比较两个人在$S$中的前后关系,将$S$用替罪羊树维护,同时维护动态标号即可$O(1)$比较。

时间复杂度$O(n\log n)$。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=400010;
typedef unsigned long long ll;
const ll inf=1ULL<<63;
const double A=0.8;
ll tl[N],tr[N],tm[N];
int size[N],son[N][2],f[N],tot,root;
int id[N],cnt;
int n,i,a[N];
void dfs(int x){
  if(son[x][0])dfs(son[x][0]);
  id[++cnt]=x;
  if(son[x][1])dfs(son[x][1]);
}
int build(int fa,int l,int r,ll a,ll b){
  int mid=(l+r)>>1,x=id[mid];
  f[x]=fa;son[x][0]=son[x][1]=0;size[x]=1;tl[x]=a;tr[x]=b;tm[x]=(a+b)>>1;
  if(l==r)return x;
  if(l<mid)size[x]+=size[son[x][0]=build(x,l,mid-1,a,tm[x])];
  if(r>mid)size[x]+=size[son[x][1]=build(x,mid+1,r,tm[x],b)];
  return x;
}
inline int kth(int k){
  if(k<1)return 0;
  int x=root,rank;
  while(1){
    rank=size[son[x][0]]+1;
    if(k==rank)return x;
    if(k<rank)x=son[x][0];else k-=rank,x=son[x][1];
  }
}
inline int rebuild(int x){
  cnt=0;
  dfs(x);
  return build(f[x],1,cnt,tl[x],tr[x]);
}
inline void fix(int x){
  int deep=1,z=x;
  size[x]++;
  while(f[z])size[z=f[z]]++,deep++;
  if(deep<log(tot)/log(1/A))return;
  while((double)size[son[x][0]]<A*size[x]&&(double)size[son[x][1]]<A*size[x])x=f[x];
  if(!x)return;
  if(x==root){root=rebuild(x);return;}
  int y=f[x],b=son[y][1]==x,now=rebuild(x);
  son[y][b]=now;
}
inline void ins(int A,int B,int x){
  if(!root){
    root=size[1]=1;
    tr[1]=inf;
    tm[1]=inf>>1;
    return;
  }
  while(1){
    if(!son[A][B]){
      son[A][B]=x;
      f[x]=A;
      if(!B){
        tl[x]=tl[A];
        tr[x]=tm[A];
      }else{
        tl[x]=tm[A];
        tr[x]=tr[A];
      }
      tm[x]=(tl[x]+tr[x])>>1;
      break;
    }
    A=son[A][B];
  }
  fix(x);
}
inline void insd(int A,int B,int x){
  if(!son[A][B]){
    son[A][B]=x;
    f[x]=A;
    if(!B){
      tl[x]=tl[A];
      tr[x]=tm[A];
    }else{
      tl[x]=tm[A];
      tr[x]=tr[A];
    }
    tm[x]=(tl[x]+tr[x])>>1;
    fix(x);
    return;
  }
  ins(son[A][B],B^1,x);
}
void show(int x){
  if(son[x][0])show(son[x][0]);
  printf("%d ",x);
  if(son[x][1])show(son[x][1]);
}
namespace DS{
int root[N],son[N][2],f[N];
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;
    else if(son[z][1]==y)son[z][1]=x;
  }
  f[x]=f[y];son[x][w^1]=y;f[y]=x;
}
inline void splay(int x){
  while(f[x]){
    int y=f[x];
    if(f[y]){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
    rotate(x);
  }
}
inline void insert(int&x,int y){
  if(!x){x=y;return;}
  int z=x;
  while(1){
    int b=tm[y]>tm[z];
    if(son[z][b])z=son[z][b];
    else{
      son[z][b]=y;
      f[y]=z;
      break;
    }
  }
  splay(x=y);
}
int ask(int&o,int y){
  int t=0,z=0,x=o;
  while(x){
    z=x;
    if(tm[x]>tm[y]){
      t=x;
      x=son[x][0];
    }else{
      x=son[x][1];
    }
  }
  if(z)splay(o=z);
  return t;
}
}
int main(){
  scanf("%d",&n);
  for(i=1;i<=n;i++){
    int x,dis;
    scanf("%d%d",&x,&dis);
    a[i]=x;
    if(i==1)ins(0,0,i);
    else{
      int y=kth(i-dis-1);
      if(a[y]==x)insd(y,1,i);
      else{
        int z=DS::ask(DS::root[x],y);
        if(z)insd(z,0,i);
        else ins(root,1,i);
      }
    }
    DS::insert(DS::root[x],i);
  }
  show(root);
}

  

E. Oneness

留坑。

F. Shuffle

对于置换中的每个循环,通过KMP求出所有可能的匹配位置,它们必然是一个等差数列。

那么对于所有循环分别列同余方程,然后扩展欧几里得求解即可。

时间复杂度$O(n)$。

#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef int ll;
const int N=1000010;
int n,i,j,p[N],vis[N],q[N];
char a[N],b[N],c[N],S[N],T[N];
int nxt[N],w[N*4];
int ans=1;
int _a[N],_b[N],tot;
namespace NT{
int flag=1;
ll k=1,m,a,r,d,x,y;
ll exgcd(ll a,ll b,ll&x,ll&y){
	if(!b)return x=1,y=0,a;
	ll d=exgcd(b,a%b,x,y),t=x;
	return x=y,y=t-a/b*y,d;
}
inline void add(ll a,ll r){
	if(r>=a)while(1);
	r%=a;
	if(!flag)return;
	d=exgcd(k,a,x,y);
	if((r-m)%d){flag=0;return;}
	x=(x*(r-m)/d+a/d)%(a/d),y=k/d*a,m=((x*k+m)%y)%y;
	if(m<0)m+=y;
	k=y;
}
void write(ll x){
	if(x>=10)write(x/10);
	int t=x%10;
	printf("%d",t);
}
void show(){
	if(flag)write(m);
	else puts("-1");
}
}
inline void solve(int len){
	int i,j,k,cnt=0;
	for(i=1;i<=len;i++)T[i]=b[q[i]],S[i]=a[q[i]];
	//printf("len=%d\n",len);
	//for(i=1;i<=len;i++)putchar(T[i]);puts("");
	//for(i=1;i<=len;i++)putchar(S[i]);puts("");
	for(nxt[1]=j=0,i=2;i<=len;nxt[i++]=j){
		while(j&&S[j+1]!=S[i])j=nxt[j];
		if(S[j+1]==S[i])j++;
	}
	//for(i=1;i<=len;i++)printf("nxt[%d]=%d\n",i,nxt[i]);
	for(i=1,j=0,k=1;i<=len*4;i++){
		while(j&&S[j+1]!=T[k])j=nxt[j];
		if(S[j+1]==T[k]){
			j++;
			if(j==len){
				w[++cnt]=i-len;
				j=nxt[j];
				//printf("find %d\n",i);
			}
		}
		k++;
		if(k>len)k=1;
	}
	if(!cnt){
		puts("-1");
		exit(0);
	}
	if(cnt<2)while(1);
	for(i=2;i<=cnt;i++)if(w[i]-w[i-1]!=w[2]-w[1])while(1);
	//printf("per=%d occ=%d\n",w[2]-w[1],w[1]);
	NT::add(w[2]-w[1],w[1]);
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main(){
	scanf("%s%s",a+1,b+1);
	n=strlen(a+1);
	for(i=1;i<=n;i++){
		int x;
		if(i<=n/2)x=i*2-1;
		else x=i*2-n;
		//printf("! %d %d\n",i,x);
		p[x]=i;
	}
	for(i=1;i<=n;i++)if(!vis[i]){
		int cnt=0;
		for(j=i;!vis[j];j=p[j])vis[j]=1,q[++cnt]=j;
		//for(j=1;j<=cnt;j++)printf("%d ",q[j]);puts("");
		solve(cnt);
	}
	NT::show();
}
/*
aaababbbbbbabbbbab
aabbabbababbbabbbb

babaaabbaa
bbaaaababa
*/

  

G. Piecewise Linearity

按题意反解出每个函数即可,精度可以取模控制,不过使用__float128也可以通过全部数据。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() {  }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n;
double xx[N], yy[N];
__float128 x[N], y[N], v[N], k[N];
const double EPS = 1e-9;
__float128 fabs(__float128 x)
{
	return x >= 0 ? x : -x;
}
bool same(__float128 x, __float128 y)
{
	x -= y;
	return x <= EPS && x >= -EPS;
}
int main()
{
	while(~scanf("%d",&n))
	{
		for(int i = 1; i <= n + 1; ++i)
		{
			scanf("%lf%lf", &xx[i], &yy[i]);
			x[i] = xx[i];
			y[i] = yy[i];
		}
		__float128 sum = 0;
		__float128 yy = 0;
		for(int i = 1; i <= n; ++i)
		{
			k[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]);
			if(i >= 2)
			{
				v[i] = (k[i] - k[i - 1]) / 2;
				sum += v[i];
				yy += v[i] * fabs(x[1] - x[i]);
			}
		}
		if(!same(sum, k[n]) || !same(-sum, k[1]) || !same(yy, y[1]))
		{
			puts("No");
		}
		else
		{
			puts("Yes");
		}
	}
	return 0;
}

/*
【trick&&吐槽】
2
-1 2
1 0
2 1

3
-3 -1
-1 -1
1 1
4 1

3
-3 1
-2 0
0 1
1 1

【题意】

【分析】

【时间复杂度&&优化】

*/

  

H. Sketch

贪心将原序列复制下来,然后构造递减数列,注意特判原序列非法的情况。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() {  }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 3e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n, m, k;
int a[N], b[N];

int main()
{
	while(~scanf("%d%d%d", &k, &n, &m)){
        a[0] = 1;
        for(int i = 1; i <= k; i ++) {
            scanf("%d", &a[i]);
            if(a[i] == -1){
                a[i] = a[i - 1];
            }
        }
        int flag = 1;
        for(int i = 2; i <= k; i ++){
            if(a[i] < a[i - 1]) flag = 0;
        }
        if(k > n || !flag){
            puts("-1");
            continue;
        }
        int rst = n - k, o = 0;
        for(int i = 1; i <= k; i ++){
            int x = m;
            while(rst > 0){
                if(x == a[i]) break;
                b[++ o] = x --;
                rst --;
            }
            b[++ o] = a[i];
        }
        /*
        if(rst){
            int x = b[o] - 1;
            while(rst > 0){
                if(x == 0) break;
                b[++ o] = x --;
                rst --;
            }
        }
        */
        if(rst){
            puts("-1");
        }
        else{
            for(int i = 1; i <= n; i ++) printf("%d ", b[i]);
            puts("");
        }
	}
	return 0;
}

/*
【trick&&吐槽】

【题意】

【分析】

【时间复杂度&&优化】

*/

  

I. $\leq$ or $\geq$

最优策略:将元素个数为$k$的栈的栈顶元素的权重设置为$2^{k-1}$,然后取加权中位数。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() {  }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;

int n, k, x;
int a[N], b[N];
char s[10];
int rst[N];
int w[20];
typedef pair<int,int>P;
P q[N];
LL pre[N][2],suf[N][2];
int main()
{
    w[1]=1;
    w[2]=2;
    w[3]=4;
    w[4]=8;
    w[5]=16;
    w[6]=32;
    w[7]=64;
    w[8]=128;
    w[9]=256;
    w[10]=512;
	while(~scanf("%d%d",&n, &k))
	{
	    for(int i = 1; i <= n; i ++) rst[i] = k;
	    while(1){
            int num = 0;
            int mx=0;
            for(int i=1;i<=n;i++)mx=max(mx,rst[i]);
            for(int i = 1; i <= n; i ++){
                scanf("%d", &b[i]);
                if(b[i])q[++num]=P(b[i],w[rst[i]]);
            }
            sort(q + 1, q + num + 1);
            LL best=~0ULL>>1;
            int pos=1;
            for(int i=1;i<=num;i++){
            	pre[i][0]=pre[i-1][0]+1LL*q[i].first*q[i].second;
            	pre[i][1]=pre[i-1][1]+q[i].second;
			}
			suf[num+1][0]=suf[num+1][1]=0;
			for(int i=num;i;i--){
            	suf[i][0]=suf[i+1][0]+1LL*q[i].first*q[i].second;
            	suf[i][1]=suf[i+1][1]+q[i].second;
			}
			for(int i=1;i<=num;i++){
				LL now=1LL*q[i].first*pre[i][1]-pre[i][0];
				now+=suf[i][0]-1LL*q[i].first*suf[i][1];
				if(now<best)best=now,pos=i;
			}
			int y=q[pos].first;
            printf("%d\n", y);
            fflush(stdout);
            scanf("%s", s);
            if(s[0] == ‘E‘){
                return 0;
            }
            else{
                for(int i = 1; i <= n; i ++){
                    if(s[0] == ‘<‘ && b[i] <= y){
                        rst[i] --;
                    }
                    else if(s[0] == ‘>‘ && b[i] >= y){
                        rst[i] --;
                    }
                }
            }
	    }
	}
	return 0;
}

/*
【trick&&吐槽】

【题意】

【分析】

【时间复杂度&&优化】

*/

  

J. Stairways

留坑。

K. Hiding a Tree

将所有可以修改编号的点的编号随机设置,然后再挑选一个影响答案的点修正异或值。

若当前方案不合法,则在有解的情况下是小概率事件,多轮随机即可。

注意生成随机编号的时候要避免与之前编号相同,因为根据生日悖论,在$10^9$内取$10^5$个随机数中有重复元素的概率超过$50%$,会导致这一轮随机作废。

#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<set>
using namespace std;
const int N=100010;
int n,i,a[N],e[N][2],b[N],c[N],q[N],m,v[N];
int used[N];
set<int>T;
inline int ask(){
	while(1){
		int x=rand()%1000000000+1;
		if(x<N&&used[x])continue;
		if(T.find(x)!=T.end())continue;
		T.insert(x);
		return x;
	}
}
void solve(){
	T.clear();
	for(i=1;i<=n;i++){
		if(a[i])b[i]=ask();
		else b[i]=i;
	}
	int ret=n;
	for(i=1;i<=n;i++)if(v[i])ret^=b[i];
	if(ret){
		if(!m)return;
		int x=rand()%m+1;
		b[q[x]]^=ret;
	}
	for(i=1;i<=n;i++){
		if(b[i]<1||b[i]>1000000000)return;
		c[i]=b[i];
	}
	sort(c+1,c+n+1);
	for(i=1;i<n;i++)if(c[i]==c[i+1])return;
	printf("%d\n",n);
	for(i=1;i<n;i++)printf("%d %d\n",b[e[i][0]],b[e[i][1]]);
	exit(0);
}
int main(){
	srand(time(NULL));
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d",&a[i]);
		if(!a[i])used[i]=1;
	}
	for(i=1;i<n;i++){
		scanf("%d%d",&e[i][0],&e[i][1]);
		v[e[i][0]]^=1;
		v[e[i][1]]^=1;
	}
	for(i=1;i<=n;i++)if(a[i]&&v[i])q[++m]=i;
	for(int _=100;_;_--)solve();
	puts("-1");
}

  

原文地址:https://www.cnblogs.com/clrs97/p/8689215.html

时间: 2024-10-07 22:28:37

XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Khamovniki的相关文章

XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Khamovniki Problem J Stairways解题报告(分块+维护凸壳)

首先ORZ一发Claris聚聚的题解:http://www.cnblogs.com/clrs97/p/8689215.html,不然我可能没机会补过这道神题了. 这里写一个更详细的题解吧(我还是太菜了啊). 题目描述 有\(n(n \le10^5)\)个人依次进入一个入口,要到一个出口.入口到出口有两条同样长的路.每个人都有一个速度,用通行时间\(a_i(1\le a_i \le 10^6)\)表示,他可以选择任一条路走.但是,若走这条路的前面的人比他慢的话,他只能降到和前面所有人最慢的那个人同

XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Peterhof.

A. City Wall 一圈一圈绕. B. Domino Colorings C. Сounterquestion 枚举 permutation 后 \(O(len)\) 地 check. D. Galaxy Center 同一层至多经过一个点. 可能 vis 的点不会太多,枚举在哪个点相遇. E. IBM 1403 预处理序列自动机,即可求 \(O(|s|)\) 出当前时间 t 下,打印字符串 s 的时间. F. Line Tracing G. The Queen and the Knigh

XVII Open Cup named after E.V. Pankratiev. Grand Prix of America (NAIPC-2017)

A. Pieces of Parentheses 将括号串排序,先处理会使左括号数增加的串,这里面先处理减少的值少的串:再处理会使左括号数减少的串,这里面先处理差值较大的串.确定顺序之后就可以DP了. 时间复杂度$O(n^3)$. #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=310,inf=1000000; int n,i,j,m,all,

XVII Open Cup named after E.V. Pankratiev Grand Prix of Moscow Workshops, Sunday, April 23, 2017 Problem D. Great Again

题目: Problem D. Great AgainInput file: standard inputOutput file: standard outputTime limit: 2 secondsMemory limit: 512 megabytesThe election in Berland is coming. The party United Berland is going to use its influence to win themagain. The crucial co

XVII Open Cup named after E.V. Pankratiev Grand Prix of Moscow Workshops, Sunday, April 23, 2017 Problem K. Piecemaking

题目:Problem K. PiecemakingInput file: standard inputOutput file: standard outputTime limit: 1 secondMemory limit: 512 mebibytesThe civil war in Berland continues for five years already. The United Nation decided to end the bloodshed.Berland consists o

XVIII Open Cup named after E.V. Pankratiev. GP of Romania

A. Balance 不难发现确定第一行第一列后即可确定全部,列不等式单纯形求解线性规划即可. #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; typedef vector<double>VD; const int N=110; const double eps=1e-9; VD simplex(vector<VD>A, VD b, VD c){

XVIII Open Cup named after E.V. Pankratiev. GP of SPb

contest Link A. Base i ? 1 Notation solved by sdcgvhgj 238 B. Squaring a Bit solved by rdc 77 本地打表,交表. C. Chickens solved by rdc, 24 f[i][mask] 表示前 i 个物品匹配 mask 集合的方案数. D. Lights at a Crossing E. Decimal Form solved by rdc, 247 -2 类欧或者SB树,然后发现自己写的类欧板

XVI Open Cup named after E.V. Pankratiev. GP of Ekaterinburg.

贼惨 130/186 B Black Widow 简单题 #include <bits/stdc++.h> const long long mod = 1e9+7; const double ex = 1e-10; #define inf 0x3f3f3f3f using namespace std; map <int,int> M; int a[1010]; int b[100010]; int main() { int N; scanf("%d",&

XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem A. Arithmetic Derivative

题目:Problem A. Arithmetic DerivativeInput file: standard inputOutput file: standard inputTime limit: 1 secondMemory limit: 256 mebibytesLets define an arithmetic derivative:? if p = 1 then p0 = 0;? if p is prime then p0 = 1;? if p is not prime then n0