ACM系列赛第一站,没有进前200仍是很伤的。git
主要是T2当时没写出来就GG了,后来看了下其实不是很难。post
题目按照比赛时咱们A的顺序讲,其实我都是被陈潇然大佬和ZWC带飞的。spa
题目大意:给出一个数字\(n\),求三个数\(x,y,z\)知足\(x,y,z|n\)且\(x+y+z=n\)。找出这样一组并使得\(xyz\)最大。有解就输出\(xyz\)的最大值,不然输出\(-1\)。code
大力猜结论,而后用ZWC当时写的一个暴力拍了下\(n\le200\)的状况发现没问题,而后就交了并1A了。排序
因此ACM猜结论成为咱们队的平常ip
如下为看起来颇有道理的结论:get
CODE数学
#include<cstdio> #include<cctype> using namespace std; int n,t; inline char tc(void) { static char fl[100000],*A=fl,*B=fl; return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++; } inline void read(int &x) { x=0; char ch; while (!isdigit(ch=tc())); while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc())); } inline void write(long long x) { if (x>9) write(x/10); putchar(x%10+'0'); } int main() { //freopen("1.in","r",stdin); freopen("1.out","w",stdout); register int i,j; read(t); while (t--) { read(n); if (n%3==0) write(1LL*(n/3)*(n/3)*(n/3)),putchar('\n'); else if (n%4==0) write(1LL*(n/4)*(n/4)*(n/2)),putchar('\n'); else puts("-1"); } return 0; }
这题我写的,感受比T1简单。string
题目大意:在平面内有保证三点不共线的\(3n\)个点,让你给出一种构造方案组成\(n\)个三角形,使得每一个三角形互不相交。it
这个数学老师上课好像讲过,咱们把三角形按\(x\)坐标排个序,而后每次三个三个取便可。这样显然不会相交。
CODE
#include<cstdio> #include<cctype> #include<algorithm> using namespace std; const int N=1005; struct data { int x,y,id; }a[N*3]; int t,n; inline char tc(void) { static char fl[100000],*A=fl,*B=fl; return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++; } inline void read(int &x) { x=0; char ch; int flag=1; while (!isdigit(ch=tc())) flag=ch^'-'?1:-1; while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc())); x*=flag; } inline void write(int x) { if (x>9) write(x/10); putchar(x%10+'0'); } inline bool cmp(data a,data b) { return a.x<b.x; } int main() { //freopen("3.in","r",stdin); freopen("3.out","w",stdout); register int i; read(t); while (t--) { for (read(n),i=1;i<=3*n;++i) read(a[i].x),read(a[i].y),a[i].id=i; sort(a+1,a+3*n+1,cmp); for (i=1;i<=3*n;i+=3) write(a[i].id),putchar(' '),write(a[i+1].id),putchar(' '),write(a[i+2].id),putchar('\n'); } return 0; }
仍是我写的,因此WA了几发。不过之后这种大力模拟题都是陈潇然大佬写的了。
题目大意:给出当前的时间(UTC +8)以及目标时区。让你求目标时区的时间。
大力模拟,有一些细节要注意:
CODE
#include<cstdio> using namespace std; int t,a,b,x,y; char ch; int main() { scanf("%d",&t); while (t--) { scanf("%d%d",&a,&b); ch=getchar(); while (ch!='+'&&ch!='-') ch=getchar(); scanf("%d",&x); y=0; if (getchar()=='.') scanf("%d",&y); if (ch=='+') { x-=8; b+=y*6; if (b>59) b-=60,++a; if (b<0) b+=60,--a; a+=x; if (a>23) a-=24; if (a<0) a+=24; } else { x+=8; b-=y*6; if (b<0) b+=60,--a; if (b>59) b-=60,++a; a-=x; if (a<0) a+=24; if (a>23) a-=24; } if (a>9) printf("%d:",a); else printf("0%d:",a); if (b>9) printf("%d\n",b); else printf("0%d\n",b); } return 0; }
这题是ZWC写的,我已经在YY线段树上二分的时候他说他用set艹过了此题。
一脸震惊,不过若是你看到下一场我用分块爆艹线段树就知道ACM的数据是极水的
题目大意:给你一个长度为\(n\)的序列以及\(m\)个限制条件,让你求一个字典序最小的序列知足对于每个限制\(,i,j\in [l_i,r_i],i\not =j\)的一对\(i,j\)都有\(a_i\not = a_j\)
首先把操做按左端点排个序,而后考虑既然是字典序最小,那么贪心的想每一次确定是把小数字的先放了。
考虑直接用set来维护一下当前能够被选择的数,那么咱们在一个区间退出时能够直接把它从set里删掉,同时在右边更新的时候把当前这个数插进去便可,取得时候也是贪心地取set里的最小值。
CODE(ZWC写的,我懒得再写一遍了)
#include<cstdio> #include<algorithm> #include<set> #define maxn 100005 using namespace std; set<int> s; int T,n,m,ans[maxn]; struct chi{ int l,r; bool operator <(const chi b)const{return l<b.l||(l==b.l&&r>b.r);} }a[maxn]; int read(){ int ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-f;ch=getchar();} while(ch>='0'&&ch<='9') {ret=ret*10+ch-'0';ch=getchar();} return ret*f; } int main(){ T=read(); while(T--){ s.clear(); n=read();m=read(); for(int i=1;i<=n;i++) s.insert(i),ans[i]=1; for(int i=1;i<=m;i++) a[i].l=read(),a[i].r=read(); sort(a+1,a+1+m); int lst=0;a[0].l=1; for(int i=1;i<=m;i++){ if(a[i].r<=a[lst].r) continue; for(int j=a[lst].l;j<a[i].l;j++) s.insert(ans[j]); for(int j=max(a[lst].r+1,a[i].l);j<=a[i].r;j++) ans[j]=*s.begin(),s.erase(s.begin()); lst=i; } for(int i=1;i<=n;i++) printf("%d%c",ans[i],n==i?'\n':' '); } return 0; }
这题以后作的,打的时候抽了没想出排序的cmp就GG了
题目大意:给出你\(n\)个括号序列,让你用合理的方法把这\(n\)个序列排好顺序后使得它们连在一块儿组成的序列中匹配的左右括号对数最多。
首先考虑先把每个序列中已经含有的对数先算出来,这个很简单吧,拿栈或者直接开一个变量模拟一下就完了,这些对数能够直接累加到答案中。
考虑将已经计算完的括号对删去,那么剩下的必定是\(')'\cdot x+'('\cdot y\)这样的形式。
首先咱们考虑全局的贪心,对于那些\(x_i>y_i\)的括号确定得先放在后面,一样的\(x_i<=y_i\)的就应该尽可能的往前放。
如今咱们考虑局部的贪心若是两个序列\(i,j\)都是\(x_i>y_i\)的形式,那么为了不浪费,咱们确定是把\(x_i\)小的放在前面。
同理,若两个序列\(i,j\)都是\(x_i<=y_i\)的形式,就要把\(y_i\)小的放在前面。
这样咱们只要写好cmp而后在模拟一遍就行了。
CODE
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=100005; struct data { int l,r; }a[N]; char s[N]; int n,ans,len,res,t; inline bool cmp(data a,data b) { if (a.l>a.r&&b.l<=b.r) return 1; if (a.l<=a.r&&b.l>b.r) return 0; if (a.l>a.r&&b.l>b.r) return a.r<b.r; return a.l>b.l; } inline int min(int a,int b) { return a<b?a:b; } int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { register int i,j; ans=res=0; for (scanf("%d",&n),i=1;i<=n;++i) { scanf("%s",s+1); len=strlen(s+1); a[i].l=a[i].r=0; for (j=1;j<=len;++j) if (s[j]=='(') ++a[i].l; else if (a[i].l) ++ans,--a[i].l; else ++a[i].r; } for (sort(a+1,a+n+1,cmp),i=1;i<=n;++i) { int p=min(res,a[i].r); ans+=p; res-=p; res+=a[i].l; } printf("%d\n",ans<<1); } return 0; }
此次题目整体偏简单,然而咱们仍是不会作
看来之后这种像T2这样的中等题要争取切掉。