今天又做了点图论和线段树的题目,比较有感触的就是这道,一开始感觉有点像hotel那道题,感觉记录区间的左右值和左右的最大频率以及总的最大频率即可,最后比较取最大,
后来在初始化的时候RE了一次,然后就AC了,感觉线段树终于入门了
import java.io.*;
public class Main {
static StreamTokenizer in = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
final static int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
class Node
{
int left,right;
int lenum,rignum;//信息域,存储该区间的左右端的元素是什么
int num,lnum,rnum;//存储左端的长度和右端长度以及最长的
Node(int left,int right)
{
this.left=left;
this.right=right;
}
int mid()
{
return (right+left)>>1;
}
int lenght()
{
return (right-left+1);
}
}
static int number;
static int MAX=100010;
static Node tree[]=new Node[MAX<<2];
static int data[]=new int[MAX];
void build(int left,int right,int idx) throws IOException
{
// System.out.println(idx+"&^&^&");
tree[idx]=new Node(left,right);
tree[idx].left=left;
tree[idx].right=right;
if(tree[idx].left==tree[idx].right)
{
tree[idx].lenum=tree[idx].rignum=data[left];
// System.out.println(data[left]);
tree[idx].lnum=tree[idx].rnum=tree[idx].num=1;
return;
}
int mid=tree[idx].mid();
build(left,mid,idx<<1);
build(mid+1,right,idx<<1|1);
tree[idx].num=tree[idx<<1].num;
if(tree[idx<<1|1].num>tree[idx].num)
tree[idx].num=tree[idx<<1|1].num;
if(tree[idx<<1].rnum+tree[idx<<1|1].lnum>tree[idx].num&&tree[idx<<1].rignum==tree[idx<<1|1].lenum)
{
tree[idx].num=tree[idx<<1].rnum+tree[idx<<1|1].lnum;
}
tree[idx].lenum=tree[idx<<1].lenum;
tree[idx].rignum=tree[idx<<1|1].rignum;
tree[idx].lnum=tree[idx<<1].lnum;
tree[idx].rnum=tree[idx<<1|1].rnum;
if(tree[idx<<1].lnum==tree[idx<<1].lenght()&&tree[idx<<1].rignum==tree[idx<<1|1].lenum)
tree[idx].lnum=tree[idx<<1].lnum+tree[idx<<1|1].lnum;
if(tree[idx<<1|1].rnum==tree[idx<<1|1].lenght()&&tree[idx<<1|1].lenum==tree[idx<<1].rignum)
tree[idx].rnum=tree[idx<<1|1].rnum+tree[idx<<1].rnum;
}
int query(int a,int b,int idx)
{
// System.out.println("idx"+idx);
if(tree[idx].left==a&&tree[idx].right==b)
{
return tree[idx].num;
}
int mid=tree[idx].mid();
// System.out.println("MID"+mid);
int ans1=-1,ans2=-1,ans3=-1,ans=-1;
if(mid>=b)
{
return query(a,b,idx<<1);
}else if(mid<a)
{
return query(a,b,idx<<1|1);
}
else
{
int temp1=query(a,mid,idx<<1);
int temp2=query(mid+1,b,idx<<1|1);
ans3=Math.max(temp1,temp2);
int temp=-1;
if(tree[idx<<1].rignum==tree[idx<<1|1].lenum)
{
if(mid-tree[idx<<1].rnum+1>=a)
{
a=mid-tree[idx<<1].rnum+1;
}
if(mid+tree[idx<<1|1].lnum<=b)
b=mid+tree[idx<<1|1].lnum;
temp=b-a+1;
}
ans3=Math.max(ans3, temp);
return ans3;
}
}
void run() throws IOException
{
while((number=nextInt())!=0)
{
int qnum=nextInt();
for(int i=1;i<=number;i++)
data[i]=nextInt();
build(1,number,1);
for(int i=1;i<=qnum;i++)
{
int a=nextInt();
int b=nextInt();
int ans=query(a,b,1);
System.out.println(ans);
}
}
}
public static void main(String[] args) throws IOException {
new Main().run();
}
}

本文探讨了图论和线段树的应用,通过解决实际问题,深入理解数据结构和算法,尤其关注初始化阶段的常见错误及优化策略。
650

被折叠的 条评论
为什么被折叠?



