A:显然最优方案是对所形成的置换的每个循环排个序。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define N 100010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,a[N],c[N];
vector<int> b;
bool flag[N];
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
for (int i=1;i<=n;i++) c[i]=a[i]=read();
sort(c+1,c+n+1);
for (int i=1;i<=n;i++) a[i]=lower_bound(c+1,c+n+1,a[i])-c;
int ans=0;
for (int i=1;i<=n;i++)
if (!flag[i])
{
flag[i]=1;int x=i;
while (!flag[a[x]]) x=a[x],flag[x]=1;
ans++;
}
cout<<ans<<endl;
memset(flag,0,sizeof(flag));
for (int i=1;i<=n;i++)
if (!flag[i])
{
b.clear();
int cnt=1;flag[i]=1;int x=i;b.push_back(i);
while (!flag[a[x]]) x=a[x],flag[x]=1,cnt++,b.push_back(x);
printf("%d ",cnt);
for (int j=0;j<cnt;j++) printf("%d ",b[j]);printf("\n");
}
return 0;
//NOTICE LONG LONG!!!!!
}

  B:随机问1000个位置,然后找到x在其中哪个区间内暴力询问即可。注意最好不要rand。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<vector>
#include<chrono>
#include<random>
using namespace std;
#define ll long long
#define N 50010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,start,x,val[N],nxt[N];
bool flag[N];
struct data{int p,val,nxt;
bool operator <(const data&a) const
{
return val<a.val;
}
}a[N];
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read(),start=read(),x=read();
mt19937 rnd(time(0));
cout<<"?"<<' '<<start<<endl;
flag[start]=1;cin>>val[start]>>nxt[start];
if (val[start]>=x) {cout<<"!"<<' '<<val[start]<<endl;return 0;}
for (int i=1;i<=999;i++)
{
int x=rnd()%n+1;
cout<<"?"<<' '<<x<<endl;
flag[x]=1;cin>>val[x]>>nxt[x];
}
int t=0;
for (int i=1;i<=n;i++) if (flag[i]) a[++t].p=i,a[t].nxt=nxt[i],a[t].val=val[i];
sort(a+1,a+t+1);
a[t+1].val=1010000000;
for (int i=1;i<=t;i++)
if (a[i].val<=x&&a[i+1].val>x)
{
int u=a[i].nxt,v=a[i].val;
if (v>=x) {cout<<"!"<<' '<<v<<endl;return 0;}
while (u!=-1&&v<x)
{
cout<<"?"<<' '<<u<<endl;
cin>>v>>u;
}
if (v>=x)
{
cout<<"!"<<' '<<v<<endl;return 0;
}
else {cout<<"!"<<' '<<-1<<endl;return 0;}
}
return 0;
//NOTICE LONG LONG!!!!!
}

  C:容易发现重心的各棵子树的点集是不能改变的。然后一堆人比如我就扔个点分上去肯定就假了。事实上可以通过这种操作将任意一棵子树展开成链,链可以再转化成菊花,分别消耗低于n次。第一步逐个考虑当前点的每个子树(都已经形成链),将当前点与父亲切断,并将该子树所形成的链的底端接到父亲。第二步由链底端自下往上切掉,并将原本的菊花中心接上即可。注意判一下有两个重心的情况。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>
#include<cassert>
using namespace std;
#define ll long long
#define N 400010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,p[N],size[N],ansx[N],ansy[N],ansz[N],fa[N],top[N],pre[N],u,root,root2,t;
set<int> e[N];
struct data{int to,nxt;
}edge[N<<1];
void addedge(int x,int y){t++;e[x].insert(y);edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void make(int k,int from)
{
size[k]=1;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from)
{
make(edge[i].to,k);
size[k]+=size[edge[i].to];
}
}
int findroot(int k,int s,int from)
{
int mx=0;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&size[edge[i].to]>size[mx]) mx=edge[i].to;
if ((size[mx]<<1)>s) return findroot(mx,s,k);
else return k;
}
void solve(int k,int from)
{
fa[k]=from;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&edge[i].to!=root&&edge[i].to!=root2) solve(edge[i].to,k);
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&edge[i].to!=root&&edge[i].to!=root2)
{
if (!top[k]) top[k]=edge[i].to;
ansx[++u]=fa[k];
ansy[u]=k;
ansz[u]=edge[i].to;
e[ansx[u]].erase(ansy[u]),e[ansx[u]].insert(ansz[u]);
e[ansy[u]].erase(ansx[u]),e[ansz[u]].insert(ansx[u]);
fa[k]=top[edge[i].to];
}
if (!top[k]) top[k]=k;
}//����kΪ�����������һ����
int get(int x)
{
while (1)
{
auto it=e[x].begin();
while (it!=e[x].end()&&(*it)==pre[x]) it++;
if (it==e[x].end()) return x;
else pre[*it]=x,x=*it;
}
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
for (int i=1;i<n;i++)
{
int x=read(),y=read();
addedge(x,y),addedge(y,x);
}
make(1,1);
root=findroot(1,n,1);
if (n%2==0)
{
for (int i=1;i<=n;i++)
if (size[i]==n/2) {root2=i;break;}
}
if (root2)
{
for (int i=p[root2];i;i=edge[i].nxt)
if (edge[i].to!=root)
{
solve(edge[i].to,root2);
pre[top[edge[i].to]]=root2;
int x=get(top[edge[i].to]),k=x;
while (k!=root2)
{
ansx[++u]=pre[k];
ansy[u]=k;
ansz[u]=x;
k=pre[k];
}
}
}
for (int i=p[root];i;i=edge[i].nxt)
if (edge[i].to!=root2)
{
solve(edge[i].to,root);
pre[top[edge[i].to]]=root;
int x=get(top[edge[i].to]),k=x;
while (k!=root)
{
ansx[++u]=pre[k];
ansy[u]=k;
ansz[u]=x;
k=pre[k];
}
}
printf("%d\n",u);
for (int i=1;i<=u;i++) printf("%d %d %d\n",ansx[i],ansy[i],ansz[i]);
return 0;
//NOTICE LONG LONG!!!!!
}

  D:注意到dij的堆如果可以用桶替代就能做到线性最短路,这要求值域较小,而题面保证了总边权变化量不超过1e6。考虑怎么仅对变化量做最短路。一开始跑完dij后,将每条边(u,v)的边权重赋值为disu+w(u,v)-disv建成新图,每次修改就在新图中进行修改并跑桶优化dij,再将得到的最短路值累加,并继续对新图进行重赋值即可。好像每次边权只+1并没有什么卵用?

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define ll long long
#define N 100010
#define inf 10000000000000000ll
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,Q,p[N],t;
ll d[N],d2[N];
bool flag[N];
vector<int> a[N];
struct data{int to,nxt;ll len;
}edge[N];
void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
struct data2
{
int x;ll d;
bool operator <( const data2&a) const
{
return d>a.d;
}
};
priority_queue<data2> q;
void dijkstra()
{
memset(d,42,sizeof(d));d[1]=0;
q.push((data2){1,0});
for (;;)
{
while (!q.empty()&&flag[q.top().x]) q.pop();
if (q.empty()) break;
data2 x=q.top();q.pop();
flag[x.x]=1;
for (int i=p[x.x];i;i=edge[i].nxt)
if (x.d+edge[i].len<d[edge[i].to])
{
d[edge[i].to]=x.d+edge[i].len;
q.push((data2){edge[i].to,d[edge[i].to]});
}
}
for (int i=1;i<=n;i++)
for (int j=p[i];j;j=edge[j].nxt)
edge[j].len=d[i]+edge[j].len-d[edge[j].to];
}
void update(int c)
{
memset(d2,42,sizeof(d2));
memset(flag,0,sizeof(flag));
for (int i=0;i<=c;i++) a[i].clear();
a[0].push_back(1);d2[1]=0;
for (int i=0;i<=c;i++)
{
for (int k=0;k<a[i].size();k++)
{
int x=a[i][k];
if (!flag[x])
{
flag[x]=1;
for (int j=p[x];j;j=edge[j].nxt)
if (d2[x]+edge[j].len<d2[edge[j].to]&&d2[x]+edge[j].len<=c)
{
d2[edge[j].to]=d2[x]+edge[j].len;
a[d2[edge[j].to]].push_back(edge[j].to);
}
}
}
}
for (int i=1;i<=n;i++)
for (int j=p[i];j;j=edge[j].nxt)
edge[j].len=d2[i]+edge[j].len-d2[edge[j].to];
for (int i=1;i<=n;i++) if (d2[i]<inf) d[i]+=d2[i];
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read(),m=read(),Q=read();
for (int i=1;i<=m;i++)
{
int x=read(),y=read(),z=read();
addedge(x,y,z);
}
dijkstra();
for (int i=1;i<=Q;i++)
{
int op=read();
if (op==1)
{
int x=read();
if (d[x]>inf) printf("-1\n");
else printf("%I64d\n",d[x]);
}
else
{
int c=read();
for (int j=1;j<=c;j++) edge[read()].len++;
update(c);
}
}
return 0;
//NOTICE LONG LONG!!!!!
}

  

AIM Tech Round 4 Div. 1的更多相关文章

  1. codeforce AIM tech Round 4 div 2 B rectangles

    2017-08-25 15:32:14 writer:pprp 题目: B. Rectangles time limit per test 1 second memory limit per test ...

  2. AIM Tech Round 3 (Div. 2)

    #include <iostream> using namespace std; ]; int main() { int n, b, d; cin >> n >> ...

  3. AIM Tech Round 3 (Div. 2) A B C D

    虽然打的时候是深夜但是状态比较好 但还是犯了好多错误..加分场愣是打成了降分场 ABC都比较水 一会敲完去看D 很快的就想出了求0和1个数的办法 然后一直wa在第四组..快结束的时候B因为低级错误被h ...

  4. AIM Tech Round 3 (Div. 2) B

    Description Vasya takes part in the orienteering competition. There are n checkpoints located along ...

  5. AIM Tech Round 3 (Div. 2) A

    Description Kolya is going to make fresh orange juice. He has n oranges of sizes a1, a2, ..., an. Ko ...

  6. AIM Tech Round 3 (Div. 2) (B C D E) (codeforces 709B 709C 709D 709E)

    rating又掉下去了.好不容易蓝了.... A..没读懂题,wa了好几次,明天问队友补上... B. Checkpoints 题意:一条直线上n个点x1,x2...xn,现在在位置a,求要经过任意n ...

  7. AIM Tech Round 3 (Div. 2) B 数学+贪心

    http://codeforces.com/contest/709 题目大意:给一个一维的坐标轴,上面有n个点,我们刚开始在位置a,问,从a点开始走,走n-1个点所需要的最小路程. 思路:我们知道,如 ...

  8. AIM Tech Round 3 (Div. 2)D. Recover the String(贪心+字符串)

    D. Recover the String time limit per test 1 second memory limit per test 256 megabytes input standar ...

  9. AIM Tech Round 4 (Div. 2)ABCD

    A. Diversity time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  10. AIM Tech Round 4 (Div. 2)(A,暴力,B,组合数,C,STL+排序)

    A. Diversity time limit per test:1 second memory limit per test:256 megabytes input:standard input o ...

随机推荐

  1. 分布式系统消息中间件——RabbitMQ的使用进阶篇

    分布式系统消息中间件--RabbitMQ的使用进阶篇 前言     上一篇文章 (https://www.cnblogs.com/hunternet/p/9668851.html) 简单总结了分布式系 ...

  2. RabbitMQ 3.6.1 升级至 3.7.9 版本(Windows 升级至Centos)

    随着公司业务量的增加,原本部署在Windows服务器的RabbitMQ集群(3.6.1)总是出现莫名其妙的问题,经查询官方Issue,确认是RabbitMQ 3.6.1 版本的bug.查看从3.6.1 ...

  3. C#里面滥用String造成的性能问题

    前两天给我们的json写一个解析函数, 之前用的正宗的json parser, 支持完整的json特性. 但是实际上我们用到特性, 只有key-value的映射, value的类型只有数字和字符串两种 ...

  4. matplotlib 入门之The Lifecycle of a plot

    文章目录 Note 数据 准备开始 操控风格 我错了!!! 定制图像 特别注意!!! figsize=(width, height)!!! 格式化标签 组合多个可视化对象? 保存你的图片 matplo ...

  5. 1060E Sergey and Subway(思维题,dfs)

    题意:给出一颗树,现在,给哪些距离为2的点对,加上一条边,问所有点对的距离和 题解:如果没有加入新的边,距离和就会等于每条边的贡献,由于是树,我们用点来代表点上面的边,对于每条边,它的贡献将是(子树大 ...

  6. poj 1486 纸张与数字匹配(二分图+割边处理)

    题目来源:http://poj.org/problem?id=1486 题意: 算出所有独一无二的字母与数字的组合,使二分图完全匹配 我以为所有点都要独一无二匹配时输出匹配方法 题解: 先得到一个完全 ...

  7. CI框架在控制器中切换读写库和读写库

    CodeIgniter框架版本:3.1.7 ,php版本:5.6.* ,mysql版本:5.6 在Ci框架中,可以在application/config/database.php中配置多个group, ...

  8. 【问题解决方案】之 jmeter启动报错:Not able to find Java executable or version. Please check your Java installation

    故事发生在云计算实验课上-- ** 故事发生在云计算实验课上-- Step 1 在Xshell中登录自己的cloud虚拟机后,<sudo su ->切换到root用户 Step 2 < ...

  9. hive条件函数

    case相当于if,when相当于=:then是条件满足的结论.否则实行else后语句,一end结束

  10. 布局管理器之BorderLayout(边界布局)

    边界布局管理器把容器的的布局分为五个位置:CENTER.EAST.WEST.NORTH.SOUTH.依次对应为:上北(NORTH).下南(SOUTH).左西(WEST).右东(EAST),中(CENT ...