本人是蒟蒻,一到比赛啥也不会,只能阿巴阿巴,赛后补题才发现我为啥没去写这些题呢┭┮﹏┭┮
A题-签到
就是给你n个机器,和m个询问,每个询问有一个s,e表示在s这个时间用掉一个机器,用到(s+e)时,用机器有顺序,优先 k-th%n的机器开始,如果他不是在用到状态,就用它。输出最忙碌的机器,一样忙碌的就按大小,从小到大输出。
我们可以先排序下查询,让开始时间短的优先查,然后用个优先队列储存当前在用的机器,和一个Treeset储存当前休息机器的编号,然后就可以出来了
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.TreeSet;
import java.io.IOException;
public class Main
{
static int n,m;
public static void main(String[] args)throws IOException
{
n=ini();m=ini();
PriorityQueue<node> queue=new PriorityQueue<node>();
TreeSet<Integer> set1=new TreeSet<Integer>();
for(int i=0;i<n;i++)set1.add(i);
node2 q[]=new node2[m];
for(int i=0;i<m;i++) q[i]=new node2(ini(),ini(),i);
Arrays.sort(q);
TreeSet<Integer> set2=new TreeSet<Integer>();
int max=0;
int maxn[]=new int[n];
go:for(int i=0;i<m;i++)
{
if(!queue.isEmpty() && queue.size()==n && queue.peek().val>q[i].s)continue;
while(!queue.isEmpty() && queue.peek().val<=q[i].s)
{
node t=queue.poll();set1.add(t.id);
}
int x=set1.first();
if(x<q[i].k) {if(set1.ceiling(q[i].k)!=null) {x=set1.ceiling(q[i].k);}}
maxn[x]++;
if(maxn[x]==max) set2.add(x);
else if(maxn[x]>max){max=maxn[x];set2.clear();set2.add(x);}
queue.add(new node(q[i].e, x));
set1.remove(x);
// System.out.println(x);
}
boolean flag=true;
for(int x:set2)
{
out.print((flag?"":" ")+x);
flag=false;
}
out.flush();
System.gc();
}
static class node implements Comparable<node>
{
int val,id;
public node(int val,int id) {
this.val=val;this.id=id;
}
public int compareTo(node o)
{
return this.val-o.val;
}
}
static class node2 implements Comparable<node2>
{
int s,e,k;
public node2(int s,int e,int k)
{
this.s=s;this.e=e+s;this.k=k%n;
}
public int compareTo(node2 o) {
int x= this.s-o.s;
if(x!=0)return x;
x= this.e-o.e;
if(x!=0)return x;
return this.k-o.k;
}
}
static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static String fs() throws IOException
{
return in.sval;
}
public static double f() throws IOException
{
return in.nval;
}
public static int ini() throws IOException
{
in.nextToken();
return (int)in.nval;
}
public static long inl() throws IOException
{
in.nextToken();
return (long)in.nval;
}
public static double ind() throws IOException
{
in.nextToken();
return in.nval;
}
public static String ins() throws IOException
{
in.nextToken();
return in.sval;
}
}
K题-签到
意思是给个t代表查询次数,然后给一个n代表有几个路由器,一个m代表有几次查询,接下来n行,每行第一个数代表第i-th个路由器连向了几个路由器,然后后面i个数代表连向的路由器编号,接下来m行,每行第一个s代表起点路由器,然后len代表走了几条路,然后后面有len个数,每个代表,s走向了刚开始连接的第条线,然后s要变成连向的路由器编号,如果是无效的路径,就输出Packet Loss,否则输出最后连向的路由器编号。
我们只需要用个list[ ]储存连向的路由器即可,注意的是遇到无效路径,不能直接输出,要继续读完剩下的数。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.TreeSet;
import java.io.IOException;
public class Main
{
static int n,m;
public static void main(String[] args)throws IOException
{
int t=ini();
for(int i=1;i<=t;i++)
{
out.printf("Case #%d: \n",i);
n=ini();m=ini();
ArrayList<Integer> list[]=new ArrayList[n+1];
for(int j=1;j<=n;j++)
{
list[j]=new ArrayList<Integer>();
list[j].add(0);
int len=ini();
while(len-->0)
{
list[j].add(ini());
}
}
for(int j=1;j<=m;j++)
{
int s=ini(),len=ini();
while(len-->0)
{
int e=ini();
if(s==0)continue;
if(e>=list[s].size())s=0;
else s=list[s].get(e);
}
if(s==0) out.println("Packet Loss");
else out.println(s);
}
}
out.flush();
System.gc();
}
static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static String fs() throws IOException
{
return in.sval;
}
public static double f() throws IOException
{
return in.nval;
}
public static int ini() throws IOException
{
in.nextToken();
return (int)in.nval;
}
public static long inl() throws IOException
{
in.nextToken();
return (long)in.nval;
}
public static double ind() throws IOException
{
in.nextToken();
return in.nval;
}
public static String ins() throws IOException
{
in.nextToken();
return in.sval;
}
}
D题-最小生成树?TLE飞了,不知道是不是我写丑了
--正解线段树or并查集
题意 就是给个t表示有t组数据,然后给个n,m,n表示有n个点,m表示连了m天,下面m行,每行一个s,e,v表示今天从s到e这几个点两两连了v长度线,求最多可以删掉多少长度的废线,使这n点仍然直接或间接的相连,如果本身就无法全部相连输出Gotta prepare a lesson,否则输出最多能删废线的总长度
首先求这m天总共用了多少绳子的计算式是 (s-e+1)*(s-e)*v/2,然后相加即可,接下来就是求最多可以删多长了,可以转换成最小可以挑选多少线就可以把全部的点连接,咋一看是最小生成树,但是肯定会超时,因为你不能把C2(s-e)这些线全走,所以可以看出把 (s+1--e)的点全部认s为老大,最后求2-n区间的最小和就可以了,这样我们就可以用线段树来求解了,先按v的长度排序,然后线段树区间暴力覆盖。
static int n,m,cnt;
static long min=0,max=0;
static int maxn=100010;
static long sum[]=new long[maxn<<2],add[]=new long[maxn<<2];//4倍空间
public static void main(String[] args)throws IOException
{
int t=in.readInt();
// build(1, maxn, 1);
for(int x=1;x<=t;x++)
{
n=in.readInt();m=in.readInt();
max=0;min=0;cnt=1;
node[] q=new node[m];
for(int i=0;i<m;i++)
{
int s=in.readInt(),e=in.readInt(),v=in.readInt();
q[i]=new node(s, e, v);
e=e-s+1;
max+=1l*e*(e-1)/2*v;
}
Arrays.sort(q, new Comparator<node>() {
public int compare(node o1, node o2) {
return o1.s-o2.s;
}
});
int l=0,r=0;
for(int i=0;i<m;i++)
{
if(i==0)
{
l=q[i].s;r=q[i].e;
}else if(r>=q[i].s) {r=Math.max(r, q[i].e);}
else break;
}
if(l!=1 || r!=n){out.printf("Case #%d: Gotta prepare a lesson\n",x);}
else
{
Arrays.sort(q, new Comparator<node>() {
public int compare(node o1, node o2) {
return o2.v-o1.v;
}
});
for(int i=0;i<m;i++) updatexiugai(q[i].s+1, q[i].e, q[i].v, 1, n, 1);
out.printf("Case #%d: %d\n",x,(max-query(2, n, 1, n, 1)));
}
}
out.close();
System.gc();
}
static class node
{
int s,e,v;
public node(int s,int e,int v)
{
this.s=s;this.e=e;this.v=v;
}
}
static void push_up(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
static void push_down(int rt,int len)
{
if(add[rt]>0)
{
add[rt<<1]=add[rt];
add[rt<<1|1]=add[rt];
sum[rt<<1]=(len-(len>>1))*add[rt];
sum[rt<<1|1]=(len>>1)*add[rt];
add[rt]=0;
}
}
static void build(int l,int r,int rt)
{
add[rt]=0;
if(l==r)
{
sum[rt]=0;
return;
}
int mid=(l+r)>>1;
build(l, mid, rt<<1);
build(mid+1, r, rt<<1|1);
push_up(rt);
}
static void updatexiugai(int a,int b,long c,int l,int r,int rt)
{
int len=r-l+1;
if(a<=l && b>=r)
{
add[rt]=c;
sum[rt]=len*c;
return;
}
push_down(rt, len);
int mid=(l+r)>>1;
if(a<=mid)updatexiugai(a, b, c, l, mid, rt<<1);
if(b>mid)updatexiugai(a, b, c, mid+1, r, rt<<1|1);
push_up(rt);
}
static long query(int a,int b,int l,int r,int rt)
{
if(a<=l && b>=r)
{
return sum[rt];
}
push_down(rt, r-l+1);
int mid=(l+r)>>1;
long ans=0;
if(a<=mid)ans+=query(a, b, l, mid, rt<<1);
if(b>mid)ans+=query(a, b, mid+1, r, rt<<1|1);
return ans;
}