This question is super wonderful.
At 30 points, you can find that there are at most n pictures in the title, and the rest are useless, so you can build nQ pieces violently and run Cruzkar.
For Q <= 50, it is found that the number of edges at this time is 2e7, and it is necessary to run Cruiser GG.
Consider prim to find the minimum spanning tree complexity nlogn + 2e7.
So you can get 50 points for violence.
Finally, consider the case of (ai-bi) <= 1.
It can be found that at this time, the connected edge has characteristics. For ai <bi, the connected edge is 2,1 3,2 4,3 ... f [i] [0] means that the edge right of i is connected to its father.
For ai == bi it is almost the same as above.
For ai> bi, one of the same cases as above will also find that there are 4, 2 5, 3 6, 4 such a connected edge method f [i] [1] represents the edge right of the point i and the father of his father. That's it.
Using the f array to update other f values can find that there is a ring, so dp can be twice. I was stupid at that time to open the smallest f array and update it.
Then do the minimum spanning tree complexity nlogn.
80 points code:
const int maxn=200010;
int n,flag,Q,vis[maxn];
vector<pii>g[maxn];
struct wy{int x,y,z;}t[maxn];
int d[maxn];ll sum;
priority_queue<pii>q;
int f[maxn][2];
inline void add(int x,int y,int z)
{
if(z>=INF)return;
if(x==y)return;
g[x].pb(mk(y,z));
g[y].pb(mk(x,z));
}
inline void prim()
{
rep(1,n,i)d[i]=INF,vis[i]=0;
d[1]=0;q.push(mk(-d[1],1));
while(q.size())
{
int x=q.top().S;q.pop();
if(vis[x])continue;
vis[x]=1;sum+=d[x];
for(int j=0;j<g[x].size();++j)
{
int tn=g[x][j].F,e=g[x][j].S;
if(d[tn]>e)
{
d[tn]=e;
q.push(mk(-d[tn],tn));
}
}
}
}
int main()
{
freopen("spanning.in","r",stdin);
freopen("spanning.out","w",stdout);
get(n);get(Q);
rep(1,Q,i)
{
int x,y,z;
get(x);get(y);get(z);
t[i]=(wy){x,y,z};
if(abs(x-y)>1)flag=1;
}
if(!flag)
{
rep(0,n-1,i)f[i][0]=f[i][1]=INF;
rep(1,Q,i)
{
int x,y,z;
x=t[i].x;y=t[i].y;z=t[i].z;
if(x==y){f[(x+1)%n][0]=min(f[(x+1)%n][0],z+1);continue;}
if(x<y)f[y][0]=min(f[y][0],z);
else
{
f[x][0]=min(f[x][0],z);
f[(x+1)%n][1]=min(f[(x+1)%n][1],z+1);
}
}
rep(0,n-1,i)
{
if(f[i][1]!=INF)q.push(mk(-f[i][1],i));
if(f[i][0]!=INF)q.push(mk(-f[i][0],i));
}
while(q.size())
{
int x=q.top().S;
int ww=-q.top().F;
q.pop();
if(ww==f[x][0])
{
int tn=(x+1)%n;
if(f[tn][0]>f[x][0]+2)
{
f[tn][0]=f[x][0]+2;
q.push(mk(-f[tn][0],tn));
}
}
if(ww==f[x][1])
{
int tn=(x+1)%n;
if(f[tn][1]>f[x][1]+2)
{
f[tn][1]=f[x][1]+2;
q.push(mk(-f[tn][1],tn));
}
}
}
rep(1,n-1,i)
{
add(i+1,i,f[i][0]);
if(i>=2)add(i+1,i-1,f[i][1]);
}
add(1,n,f[0][0]);
add(1,n-1,f[0][1]);
add(2,n,f[1][1]);
prim();putl(sum);
return 0;
}
if(flag)
{
if((ll)n*Q<=10000000)
{
rep(1,Q,i)
{
int x=t[i].x;int y=t[i].y;int z=t[i].z;
int s1=0,s2=0;add(x+1,y+1,z);
rep(1,n*2-1,j)
{
if(j&1)++s1;else ++s2;
add((s1+x)%n+1,(s2+y)%n+1,z+j);
}
}
sum=0;prim();putl(sum);
}
}
return 0;
}
Considering 100 points, we can still find that this is a problem of optimizing construction.
Consider the process of Kruskal. For edges a, b, and ca, connect b to a side of c. For the next side, a + 1, b, c + 1. When the previous edge is smaller than the current edge weight, when the previous edge is convenient, a, b must form a fast connection.
At this time, the side a + 1, b, c + 1 is equivalent to a + 1, a, c + 1 and the next side a + 1, b + 1, c + 2 can be converted to b, b + 1, c + 2.
Let f [i] represent the minimum dp of the edge weight of point i and its father's connected edges. It can be found that all the edges are simplified in this way.
Then run Cruiser to get the total number of edges Q + n. Complexity (Q + n) log.
const int MAXN=400010;
int n,cnt,Q;ll sum;
struct wy
{
int x,y,z;
}t[MAXN<<1];
int f[MAXN];
inline int cmp(wy a,wy b){return a.z<b.z;}
inline int getfather(int x){return x==f[x]?x:f[x]=getfather(f[x]);}
int main()
{
freopen("spanning.in","r",stdin);
freopen("spanning.out","w",stdout);
memset(f,0x3f,sizeof(f));
get(n);get(Q);
rep(1,Q,i)
{
int x,y,z;
get(x);get(y);get(z);
t[++cnt]=(wy){x+1,y+1,z};
f[(x+1)%n]=min(f[(x+1)%n],z+1);
f[(y+1)%n]=min(f[(y+1)%n],z+2);
}
rep(1,n-1,i)f[i]=min(f[i-1]+2,f[i]);
f[0]=min(f[n-1]+2,f[0]);
rep(1,n-1,i)f[i]=min(f[i-1]+2,f[i]);
rep(1,n-1,i)t[++cnt]=(wy){i,i+1,f[i]};
t[++cnt]=(wy){1,n,f[0]};
rep(1,n,i)f[i]=i;
sort(t+1,t+1+cnt,cmp);
rep(1,cnt,i)
{
int xx=getfather(t[i].x);
int yy=getfather(t[i].y);
if(xx==yy)continue;
f[xx]=yy;sum+=t[i].z;
}
putl(sum);
return 0;
}