The 2021 ICPC Asia Regionals Online Contest (I) 补题 --------()┭┮﹏┭┮--java

2 篇文章 0 订阅
1 篇文章 0 订阅

本人是蒟蒻,一到比赛啥也不会,只能阿巴阿巴,赛后补题才发现我为啥没去写这些题呢┭┮﹏┭┮



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;
	    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值