博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
XVIII Open Cup named after E.V. Pankratiev. Eastern Grand Prix
阅读量:6533 次
发布时间:2019-06-24

本文共 12878 字,大约阅读时间需要 42 分钟。

A. Artifacts

建立语法分析树,首先根据上下界判断是否有解,然后将所有数按下界填充,线段树判断是否存在和超过$K$的子区间。

 

B. Brackets and Dots

最优解中一定包含一对中间都是点的$()$,set维护所有这种pair即可。

#include
#include
#include
#include
using namespace std;typedef pair
P;const int N=500010;int n,i,m,x,y;set
A;set

B;char a[N];inline bool gao(int x,int y){ set

::iterator it=B.lower_bound(P(x,-1)); if(it==B.end())return 0; if(it->second>y)return 0; int l=it->first,r=it->second; B.erase(it); set

::iterator i=A.find(l),j=A.find(r); int pre=0,nxt=0; if(i!=A.begin()){ i--; if(a[*i]=='(')pre=*i; } j++; if(j!=A.end()){ if(a[*j]==')')nxt=*j; } A.erase(l); A.erase(r); if(pre&&nxt)B.insert(P(pre,nxt)); return 1;}int main(){ scanf("%s",a+1); n=strlen(a+1); for(i=1;i<=n;i++){ A.insert(i); if(a[i]=='('&&a[i+1]==')')B.insert(P(i,i+1)); } scanf("%d",&m); while(m--){ scanf("%d%d",&x,&y); int ans=0; while(gao(x,y))ans++; printf("%d\n",ans*2); }}

  

C. Crossword

首先$O(n^2)$预处理出竖着的两条对于每种间隔的贡献,然后$O(n^2)$枚举横着的摆法,再根据预处理的数组求出每个位置竖着的放法,前缀和优化即可。

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

#include
#include
#include
#include
#include
#include
using namespace std;string a[9];int q[9],i;long long ans;int f[555],g[555];int wc[160][29][29],wd[160][29][29];inline int cal(const string&A,int d,char x,char y){ int ret=0; for(int i=d;i
>a[i]; for(int j=0;j

  

D. Digit

从高位到低位贪心。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;void fre() { }#define MS(x, y) memset(x, y, sizeof(x))#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template
inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }template
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
inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }int casenum, casei;int n, l;int cnt[10];vector
vt[10];int w[10];bool ok[N];int ans[N];char s[N];int solve(){ MS(ok, 0); MS(w, 0); int p = n + 1; while(p > 1 && s[p - 1] == '9')--p; ok[p - 1] = 1; bool can = ok[0]; for(int i = 1; i <= n; ++i) { can |= ok[i]; if(can) { for(int j = 1; j <= s[i] - '0'; ++j)w[j]++; } else { int top = s[i] - '0' - 1; if(top == 0 && s[i] == '1')top = 1; for(int j = 1; j <= top; ++j)w[j]++; } } int v = -1; int g = -1; for(int i = 9; i >= 0; --i) { if(w[i] > g) { g = w[i]; v = i; } } return v;}void table(){ for(n = 1; n <= 9999; ++n) { int x = n; while(x) { ++cnt[x % 10]; x /= 10; } int v = -1; int g = -1; for(int i = 9; i >= 0; --i) { if(cnt[i] > g) { g = cnt[i]; v = i; } } ans[n] = v; //vt[v].push_back(n); } for(int i = 1; i <= 9; ++i) { printf("# %d: ", i); for(auto x : vt[i])printf("%d ", x); puts(""); }}int main(){ //table(); while(~scanf("%s",s + 1)) //for(int x = 1; x <= 9999; ++x) { //sprintf(s + 1, "%d", x); n = strlen(s + 1); int ans1 = solve(); //printf("%d:\n", x); printf("%d\n", ans1); /* int ans2 = ans[x]; printf("%d\n", ans2); if(ans1 != ans2) while(1); */ //int x; sscanf(s + 1, "%d", &x); //printf("%d\n", ans[x]); } return 0;}/*【trick&&吐槽】【题意】【分析】【时间复杂度&&优化】*/

  

E. Enormous Table

找规律。

#include
#include
#include
#include
using namespace std;const int N= 1e6 + 10;typedef long long LL;LL a, b;int main(){ while(~ scanf("%lld%lld", &a, &b)){ LL x = a + b - 2; LL y = (1 + x) * x / 2; LL ans; if((a + b) & 1) ans = y + a; else ans = y + b; printf("%lld\n", ans); } }/*4 7 1 41 21 21 42 32 33 43 44 3 1 21 22 44 35 8 3 13 25 23 44 54 12 13 53 1*/

  

F. Funny Language

首先可以$O(n\log n)$枚举出所有位于同一段序列内部的区间$\gcd$,只需要考虑横跨了多个序列的情况。

考虑容斥,设$f_d$表示$d|\gcd$的方案数,则实际值$g_d=f_d-g_{2d}-g_{3d}-...$,可以在$O(n\log n)$的时间内求出所有$g$。

考虑如何求$f_d$:对于每个序列计算有多少个前后缀是$d$的倍数,以及整个序列是否是$d$的倍数,枚举横跨序列的个数用组合数计算答案即可。

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

#include
#include
using namespace std;const int N=80010,P=1000000007;int D,i,j,fac[N],inv[N],ans[N],fin;int n,len[N],st[N],en[N],pool[N],cur,base;int vis[N],vl[N],vr[N],ok[N],all,m,q[N];int sl[2],sr[2],slr[2];vector
vpre[N],vsuf[N],vall[N];int gcd(int a,int b){return b?gcd(b,a%b):a;}inline int C(int n,int m){return n
1&&gcd(a[i],v[l[j]-1])==gcd(a[i],v[j]))l[j]=l[l[j]-1]; up(ans[v[j]],1LL*(j-l[j]+1)*base%P); }}inline void visit(int x){ if(vis[x]==D)return; vis[x]=D; vl[x]=vr[x]=ok[x]=0; q[++m]=x;}inline int work(){ int i,j,k,x,y,ret,ans=0; all=m=0; for(i=D;i
=st[i];j--){ suf=gcd(suf,pool[j]); vsuf[suf].push_back(i); } } for(D=1;D

  

G. Game of Tic-Tac-Toe

总状态只有$2\times 3^9$,博弈DP后即可得到下棋策略。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;void fre() { }#define MS(x, y) memset(x, y, sizeof(x))#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template
inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }template
inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }const int N = 1010, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;template
inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }int casenum, casei;int n;int f[3*3*3*3*3*3*3*3*3][2];int a[3][3];int check(){ int j = 0; for(int i = 0; i < 3; ++i) { if(a[i][j] == 0 && a[i][j + 1] == 0 && a[i][j + 2] == 0)return 0; if(a[j][i] == 0 && a[j + 1][i] == 0 && a[j + 2][i] == 0)return 0; if(a[i][j] == 1 && a[i][j + 1] == 1 && a[i][j + 2] == 1)return 1; if(a[j][i] == 1 && a[j + 1][i] == 1 && a[j + 2][i] == 1)return 1; } if(a[0][0] == 0 && a[1][1] == 0 && a[2][2] == 0)return 0; if(a[0][2] == 0 && a[1][1] == 0 && a[2][0] == 0)return 0; if(a[0][0] == 1 && a[1][1] == 1 && a[2][2] == 1)return 1; if(a[0][2] == 1 && a[1][1] == 1 && a[2][0] == 1)return 1; return 2;}int v[10];void getA(int x){ for(int j = 0; j < 9; ++j) { a[j / 3][j % 3] = x % 3; if(a[j / 3][j % 3]) -- a[j / 3][j % 3]; else a[j / 3][j % 3] = 2; x /= 3; }}int main(){ int top = 3*3*3*3*3*3*3*3*3; v[0] = 1; for(int i = 1; i <= 9; ++i)v[i] = v[i - 1] * 3; for(int i = top - 1; i >= 0; --i) { getA(i); int win = check(); if(win < 2) { //printf("win status %d: %d\n", i, win); f[i][0] = f[i][1] = win; continue; } bool end = 1; for(int j = 0; j < 9; ++j) { if(a[j / 3][j % 3] == 2) { end = 0; } } if(end) { f[i][0] = f[i][1] = 2; continue; } for(int k = 0; k < 2; ++k)//who play { bool can_draw = 0; f[i][k] = -1; for(int j = 0; j < 9; ++j) { if(a[j / 3][j % 3] == 2) { int nxt = i + v[j] * (k + 1); if(f[nxt][1 ^ k] == k) { f[i][k] = k; } else if(f[nxt][1 ^ k] == 2) { can_draw = 1; } } } if(f[i][k] == -1) { f[i][k] = can_draw ? 2 : (1 ^ k); } } } //printf("%d\n", f[0][0]); char C; scanf(" %c", &C); { int me = 1, ene = 0; int step = 0; int now = 0; if(C == 'O') { int y, x; scanf("%d%d", &y, &x); --y; --x; now += v[y * 3 + x] * 1; ++step; } getA(now); //printf("sta: %d, %d\n", now, f[now][me]); while(step < 9) { int y = -1; int x = -1; for(int i = 0; i < 3; ++i) { for(int j = 0; j < 3; ++j)if(a[i][j] == 2) { int nxt = now + v[i * 3 + j] * 2; //printf("ene: %d %d\n", nxt, f[nxt][ene]); if(f[nxt][ene] != ene) { y = i; x = j; } } } printf("%d %d\n", y + 1, x + 1); fflush(stdout); now += v[y * 3 + x] * 2; ++step; getA(now); char s[100]; scanf("%s", s); if(isalpha(s[0]))return 0; sscanf(s, "%d", &y); scanf("%s", s); sscanf(s, "%d", &x); --y; --x; now += v[y * 3 + x] * 1; ++step; getA(now); } } return 0;}/*【trick&&吐槽】【题意】【分析】【时间复杂度&&优化】*/

  

H. Hill and Subhill

高维差分。

#include
#include
#define FOR(i,a,b) for(int i=a;i<=b;i++)#define FOV(i,a,b) for(int i=a;i>=b;i--)#define CLR(a) memset(a,0,sizeof a)#define U 105][105][105#define FFF FOR(i,1,N)FOR(j,1,i)FOR(k,1,j)#define VVV FOV(i,N,1)FOV(j,i,1)FOV(k,j,1)typedef long long LL;int N,M,Q,x,y,z,a,d3as[U],d3ae[U],d3ds[U],d3de[U];LL d2a[U],d2d[U],d1[U],suffix1d[U],suffix2d[U],s1[U],s2[U],s31[U],s32[U];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';}void solve(){ int x,y,z,a; CLR(d3as); CLR(d3ae); CLR(d3ds); CLR(d3de); CLR(d2a); CLR(d2d); CLR(d1); CLR(suffix1d); CLR(suffix2d); CLR(s1); CLR(s2); CLR(s31); CLR(s32); for(int i=0;i

  

I. It is panic?

按题意模拟。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;void fre() { }#define MS(x, y) memset(x, y, sizeof(x))#define ls o<<1#define rs o<<1|1typedef long long LL;typedef unsigned long long UL;typedef unsigned int UI;template
inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }template
inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }const int N = 1010, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;template
inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }int casenum, casei;int n;char s[N];int main(){ while(~scanf("%s",s)) { int n = strlen(s); int l = -1; while(l < n - 1 && s[l + 1] == 'A')++l; int r = n; while(r > 0 && s[r - 1] == '!')--r; if(l >= 0 && r < n && r == l + 1)puts("Panic!"); else puts("No panic"); } return 0;}/*【trick&&吐槽】【题意】【分析】【时间复杂度&&优化】*/

  

J. JokeCoin

按左端点排序,树状数组维护右端点即可优化DP至$O(n\log n)$。

#include
#include
#include
using namespace std;typedef vector
V;typedef long long ll;const int N=200010,M=25,P=1000000007;int n, m;struct A{ int st, ed, v;}a[N];inline bool cmp(const A&a,const A&b){ return a.st

  

K. King and ICPC

分治,预处理出$mid$到$[l,r]$每个点的背包,然后利用这个信息处理所有经过$mid$的询问。

时间复杂度$O((nd+m)\log n+md)$。

#include
#include
using namespace std;typedef vector
V;typedef long long ll;const int N=50010,M=55;const ll inf=1LL<<60;int n,m,q,i,j,a[N][3];ll f[N][M],g[N][M];int e[300010][2];ll ans[300010];inline void up(ll&a,ll b){a
r||!v.size())return; int mid=(l+r)>>1; int i,j,k; //[l..mid] [mid+1..r] for(i=l;i<=mid+1;i++)for(j=0;j
=l;i--)for(j=0;j
<3;k++)up(f[i][(j+a[i][k])%m],f[i+1][j]+a[i][k]); for(i=mid;i<=r;i++)for(j=0;j
mid)vr.push_back(x); else{ for(j=0;j

  

L. Longest Simple Paths

Dijkstra求出最短路树后点分治统计即可。

#include
#include
const int N=30010,M=120010,inf=~0U>>1;int n,m,k,i,x,y,z,g[N],v[M],w[M],nxt[M],ok[M],ed,d[N],vis[N],son[N],f[N],size,now,T,pos[N];struct E{int x,y,w;E(){}E(int _x,int _y,int _z){x=_x,y=_y,w=_z;}}a[M];inline bool cmp(E a,E b){return a.x==b.x?a.y>b.y:a.x
='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];ok[ed]=1;g[x]=ed;}struct Num{ int x,y; Num(){x=y=0;} Num(int _x,int _y){x=_x,y=_y;} inline Num operator+(Num b){ if(x==b.x)return Num(x,y+b.y); return x
>1; build(x<<1,a,mid),build(x<<1|1,mid+1,b);}inline void change(int x,int a,int b,int c,int d){ if(a==b){val[x].x=d;return;} int mid=(a+b)>>1; c<=mid?change(x<<1,a,mid,c,d):change(x<<1|1,mid+1,b,c,d); val[x]=val[x<<1]+val[x<<1|1];}void dfs(int x){ vis[x]=1; for(int i=g[x];i;i=nxt[i])if(!vis[v[i]]&&d[x]+w[i]==d[v[i]])a[++m]=E(x,v[i],w[i]),dfs(v[i]);}void findroot(int x,int pre){ son[x]=1;f[x]=0; for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=pre){ findroot(v[i],x); son[x]+=son[v[i]]; if(son[v[i]]>f[x])f[x]=son[v[i]]; } if(size-son[x]>f[x])f[x]=size-son[x]; if(f[x]
=k)return; Num t=get(k-dep); if(t.y)ans+=Num(t.x+sum,t.y); for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=pre)dfscal(v[i],x,dep+1,sum+w[i]);}void dfsadd(int x,int pre,int dep,int sum){ if(dep>=k)return; up(dep,Num(sum,1)); for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=pre)dfsadd(v[i],x,dep+1,sum+w[i]);}void solve(int x){ int i; T++,up(1,Num(0,1)); for(i=g[x];i;i=nxt[i])if(ok[i])dfscal(v[i],x,2,w[i]),dfsadd(v[i],x,2,w[i]); for(i=g[x];i;i=nxt[i])if(ok[i])ok[i^1]=0,f[0]=size=son[v[i]],findroot(v[i],now=0),solve(now);}int main(){ read(n),read(m),read(k);k++; for(i=1;i<=m;i++){ read(x),read(y),read(z); a[i]=E(x,y,z); a[i+m]=E(y,x,z); } std::sort(a+1,a+m+m+1,cmp); for(i=1;i<=m+m;i++)add(a[i].x,a[i].y,a[i].w); for(i=2;i<=n;i++)d[i]=inf; build(1,1,n),change(1,1,n,1,0); while(val[1].x

  

转载地址:http://jkzdo.baihongyu.com/

你可能感兴趣的文章
linux系统配置之bash shell的配置(centos)
查看>>
linux C 9*9
查看>>
hdu 1695: GCD 【莫比乌斯反演】
查看>>
python的string操作总结
查看>>
如何把word中的图片怎么导出来呢?
查看>>
CMD指令大全
查看>>
十五天精通WCF——第二天 告别烦恼的config配置
查看>>
Qt多线程学习:创建多线程
查看>>
设计模式学习---UML常见关系的实现
查看>>
图解openssl实现私有CA
查看>>
BZOJ2213 : [Poi2011]Difference
查看>>
c++ Constructor FAQ 继续
查看>>
事务之六:spring 嵌套事务
查看>>
C#:路径
查看>>
js表单计算金额问题
查看>>
iOS图片加载速度极限优化—FastImageCache解析
查看>>
PHP中的一些新特性
查看>>
Jmockit使用
查看>>
I.MX6 Android mmm convenient to use
查看>>
[CareerCup] 13.9 Aligned Malloc and Free Function 写一对申请和释放内存函数
查看>>