Dashboard - The 2023 ICPC Asia Hangzhou Regional Contest (The 2nd Universal Cup. Stage 22: Hangzhou) - Codeforces
to sum of:从结果上来看,是打的最好的一次(铜首),罚时少75左右到银牌区了。过程也顺利,陆陆续续都在有题出,最后一个小时过了还出了两题。签到题智慧了一下35分钟出的,虽然wa了一发,但是也没有卡太久,如果没有智慧一下的话,不知道还会卡多久..然后出的第二题是交互题,第三题是从开场到后场队友一直在想的构造题,我没有看,想不来..然后第四题是期望题,也是队友写的,我完全写不来一点。然后最一题是一个最短路,思路出的挺快,但是不确定,后来还换了别的想法,都实现不了。然后倒回去想一开始那个,发现的确完全是可以那样写的。敲了一发没测样例wa1,然后再交TLE4,再把unordered_map换成数组(一开始以为太大了)跑了1700ms,给了2s,可以跑过。题解说还能把优先队列给优化了,但是不是很清楚。总的来说,在成都赛站前能打这么一次顺利的,优异的vp,可以了,士气大涨!
按出题顺序:
Problem - M - Codeforces--V-Diagram
思路:签到题,还是得智慧一下,不然卡多久都不知道。智慧:如果决定把最大的值去掉,那一边就应该全部都去掉。另一边也是。所以只有几种情况匹配,要么两边都不删,要么都删,要么删其中一边。取max即可。
void solve(){
cin >> n;
double sum=0;
double sum1=0,sum2=0,sum3=0;
int idx=0;
for(int i=1;i<=n;i++){
cin >> a[i];
if(i>1 && a[i-1]<a[i] && a[i-1]<a[i-2]) idx=i-1;
sum+=a[i];
}
for(int i=1;i<=idx+1;i++) sum1+=a[i];
for(int i=idx-1;i<=n;i++) sum2+=a[i];
sum3=a[idx-1]+a[idx]+a[idx+1];
double ns=sum;
double avg=sum/n;
avg=max({sum1/(idx+1),sum2/(n-idx+2),sum3/3,avg,ns/n});
cout << fixed << setprecision(11) << avg << "\n";
}
Problem - J - Codeforces--MysteriousTree
思路:交互题。只能问500+3次,容易发现,只要在500次之内问出来一条边,那么剩下三次肯定可以得出结论。一开始想着固定一个数字,然后一直问奇数,发现是不行的。后来发现只要1,2--3,4--5,6--7,8--这样问,500次肯定可以问出一条边,如果一直没有边那肯定就是链,否则需要再用三次判断一下。
int n;
void solve(){
cin>>n;
int u=1,v=2;
if(n%2==0){
int ans=0;
while(1){
cout<<"? "<<u<<" "<<v<<endl;
cin>>ans;
if(ans==1){
if(u-1>=1) cout<<"? "<<u<<" "<<u-1<<endl;
else cout<<"? "<<u<<" "<<v+1<<endl;
cin>>ans;
if(ans==1){
if(u-1>=1&&u-2>=1) cout<<"? "<<u<<" "<<u-2<<endl;
else if(u-1>=1&&u-2<1) cout<<"? "<<u<<" "<<v+1<<endl;
else cout<<"? "<<u<<" "<<v+1+1<<endl;
cin>>ans;
if(ans==1){ cout<<"! 2"<<endl; return; }
else { cout<<"! 1"<<endl; return; }
}
else{
if(u-1>=1) cout<<"? "<<v<<" "<<u-1<<endl;
else cout<<"? "<<v<<" "<<v+1<<endl;
cin>>ans;
if(ans==1){
if(u-1>=1&&u-2>=1) cout<<"? "<<v<<" "<<u-2<<endl;
else if(u-1>=1&&u-2<1) cout<<"? "<<v<<" "<<v+1<<endl;
else cout<<"? "<<v<<" "<<v+1+1<<endl;
cin>>ans;
if(ans==1){ cout<<"! 2"<<endl; return; }
else { cout<<"! 1"<<endl; return; }
}
else{ cout<<"! 1"<<endl; return; }
}
}
else {
if(u==n-1&&v==n){ cout<<"! 1"<<endl; return; }
u+=2,v+=2;
}
}
}
else{
int ans=0;
while(1){
cout<<"? "<<u<<" "<<v<<endl;
cin>>ans;
if(ans==1){
if(u-1>=1) cout<<"? "<<u<<" "<<u-1<<endl;
else cout<<"? "<<u<<" "<<v+1<<endl;
cin>>ans;
if(ans==1){
if(u-1>=1&&u-2>=1) cout<<"? "<<u<<" "<<u-2<<endl;
else if(u-1>=1&&u-2<1) cout<<"? "<<u<<" "<<v+1<<endl;
else cout<<"? "<<u<<" "<<v+1+1<<endl;
cin>>ans;
if(ans==1){ cout<<"! 2"<<endl; return; }
else { cout<<"! 1"<<endl; return; }
}
else{
if(u-1>=1) cout<<"? "<<v<<" "<<u-1<<endl;
else cout<<"? "<<v<<" "<<v+1<<endl;
cin>>ans;
if(ans==1){
if(u-1>=1&&u-2>=1) cout<<"? "<<v<<" "<<u-2<<endl;
else if(u-1>=1&&u-2<1) cout<<"? "<<v<<" "<<v+1<<endl;
else cout<<"? "<<v<<" "<<v+1+1<<endl;
cin>>ans;
if(ans==1){ cout<<"! 2"<<endl; return; }
else { cout<<"! 1"<<endl; return; }
}
else{ cout<<"! 1"<<endl; return; }
}
}
else if(u==n-2) u++,v++;
else {
if(u==n-1&&v==n){ cout<<"! 1"<<endl; return; }
u+=2,v+=2;
}
}
}
}
D (codeforces.com)--OperatorPrecedence
思路:队友写的构造题,不懂。
bool check(vector<int> ans) {
int r1 = 0, r2 = 0;
for (int i = 1;i < (int)ans.size(); i += 2) {
r1 += (ans[i] * ans[i + 1]);
}
r2 = ans[1] * ans.back();
for (int i = 2; i < (int)ans.size() - 1; i += 2) {
r2 *= (ans[i] + ans[i + 1]);
}
return (r1 == r2) && r1;
}
void solve(){
cin >> n;
if (n == 2) {
cout << "1 -3 -3 1" << '\n';
return ;
}
vector<int> ans(n * 2 + 1);
if (n & 1) {
vector<int> t = {-2, 2, 2, -2}, tt = {1, 1, -1, -1};
for (int i = 2, j = 0; i <= n * 2; i += 2, j ++) {
j %= 4;
ans[i] = t[j];
}
for (int i = 1, j = 0; i <= n * 2; i += 2, j ++) {
j %= 4;
ans[i] = tt[j];
}
} else {
vector<int> t = {-2, 2, 2, -2}, tt = {1, 1, -1, -1};
for (int i = 2, j = 0; i <= n * 2; i += 2, j ++) {
j %= 4;
ans[i] = t[j];
}
for (int i = 1, j = 0; i <= n * 2; i += 2, j ++) {
j %= 4;
ans[i] = tt[j];
}
if (n % 4 == 2) {
ans[n * 2] = 1;
ans[n * 2 - 2] = 1;
} else {
ans[n * 2] = 2;
ans[n * 2 - 2] = 4;
}
}
for (int i = 1; i <= n * 2; i ++) cout << ans[i] << ' ';
cout << '\n';
// if (check(ans)) cout << "YES" << '\n';
// else cout << "NO"<< '\n';
}
Problem - H - Codeforces--SugarSweet2
思路:队友写的期望题,不懂。
ll n;
ll qpow(ll a,ll n){
ll res=1;
while(n){
if(n&1) (res*=a)%=mod;
(a*=a)%=mod;
n>>=1;
}
return res;
}
ll fac[N],inv[N];
void init(int x){
fac[0]=1;
for(int i=1;i<=x;i++) fac[i]=fac[i-1]*i%mod;
inv[x]=qpow(fac[x],mod-2);
for(int i=x-1;~i;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
ll a[N],b[N],w[N];
ll c[N];
int fa[N];
int fnd(int x){
return fa[x]==x?x:fa[x]=fnd(fa[x]);
}
bool vi[N];
int dfs(int x){
vi[x]=1;
if(b[x]==x){c[x]=a[x]; return 0;}
if(a[b[x]]+w[b[x]]<=a[x]){
c[x]=a[x];
return 0;
}
if(a[b[x]]>a[x]){
c[x]=(a[x]+w[x])%mod;
return 1;
}
int to=b[x];
if(fnd(to)==x){c[x]=a[x]; return 0;}
fa[x]=to;
ll res=dfs(to);
if(!res){c[x]=a[x]; return 0;}
else c[x]=(a[x]+w[x]*inv[res+1]%mod)%mod;
return res+1;
}
void solve(){
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
fa[i]=i,vi[i]=0;
}
for(int i=1;i<=n;i++){
cin >> b[i];
}
for(int i=1;i<=n;i++){
cin >> w[i];
}
for(int i=1;i<=n;i++) if(!vi[i]) dfs(i);
for(int i=1;i<=n;i++) cout << c[i] << " \n"[i==n];
}
Problem - G - Codeforces--SnakeMove
思路:非常容易发现是最短路,但是怎么处理与身体碰撞?其实只需要考虑一开始的静态的位置,后面动起来之后蛇身变化的位置没必要维护,因为我头到达的地方肯定是合法的位置,而只有我的蛇头到达过了那个点,蛇身才会在后来到达那个点。除了一开始蛇身会发生碰撞,后面bfs中可能会发生的碰撞是完全不用考虑的,因为肯定是更劣的,第一次蛇头到达才是更优的。那么只跑最短路,然后期间判断一下一开始是蛇身即可。因为用了优先队列,时间复杂度是o(nm*log(nm))的,给了2s,跑了1700ms。题解说可以优化成用普通队列o(nm)就行,暂时不是清楚..
int n,m,k;
int have[10000010];
char maze[3003][3003];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
unsigned long long dis[3003][3003];
bool vis[3003][3003];
inline void dijkstra(int x0,int y0){
dis[x0][y0]=0;
priority_queue<pair<int,pair<int,int>>,vector<pair<int,pair<int,int>>>,greater<>> pq;
pq.push({0,{x0,y0}});
while(pq.size()){
pair<int,int> from=pq.top().second;
pq.pop();
int xx0=from.first,yy0=from.second;
if(vis[xx0][yy0]) continue;
vis[xx0][yy0]=1;
for(int i=0;i<4;i++){
int x=xx0+dx[i];
int y=yy0+dy[i];
if(x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y]&&maze[x][y]!='#'){
if(have[(x-1)*m+y]==k-2&&xx0==x0&&yy0==y0){
dis[x][y]=k-1;
pq.push({dis[x][y],{x,y}});
}
else if(have[(x-1)*m+y]!=0&&dis[xx0][yy0]+1>(unsigned long long)have[(x-1)*m+y]){
if(dis[x][y]>dis[xx0][yy0]+1){
dis[x][y]=dis[xx0][yy0]+1;
pq.push({dis[x][y],{x,y}});
}
}
else if(have[(x-1)*m+y]!=0){
if(dis[x][y]>have[(x-1)*m+y]-(dis[xx0][yy0]+1)+1+dis[xx0][yy0]+1){
dis[x][y]=have[(x-1)*m+y]-(dis[xx0][yy0]+1)+1+dis[xx0][yy0]+1;
pq.push({dis[x][y],{x,y}});
}
}
else{
if(dis[x][y]>dis[xx0][yy0]+1){
dis[x][y]=dis[xx0][yy0]+1;
pq.push({dis[x][y],{x,y}});
}
}
}
}
}
}
void solve(){
cin>>n>>m>>k;
int x0,y0;
for(int i=1;i<=k;i++){
int x,y; cin>>x>>y;
have[(x-1)*m+y]=k-i;
if(i==1) x0=x,y0=y;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>maze[i][j];
dis[i][j]=INT_MAX/2;
}
}
dijkstra(x0,y0);
unsigned long long ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(dis[i][j]!=INT_MAX/2) ans+=dis[i][j]*dis[i][j];
// cout<<dis[i][j]<<" ";
}
// cout<<"\n";
}
cout<<ans;
}
//勿以小赢而不麻