青岛网络赛补题...

太菜了….没办法….都要准备退水了,简单记录一下吧
1008和1011都是水题,没什么好说的,就是简单的模拟,这里说一下。

1003The Dominator of Strings(HDU 6208)

是一个AC自动机…原来没有接触过,和HDU2222非常像,然后运用kuangbin大佬的模板嗯!但是这里存在一个小小的问题,如何去选择最长的串呢?然后经过大佬赛后交流得知,用滚动数组记录即可!涨姿势

#include<bits/stdc++.h>
using namespace std;
const int N=26;
const int MAXN=100010;
struct Trie{
    int next[MAXN][N],fail[MAXN],end[MAXN];
    int root;
    int tot;
    int newnode()
    {
        for(int i=0;i<N;i++)
                next[tot][i]=-1;
        end[tot++]=0;
        return tot-1;
    }
    void init()
    {
        tot=0;
        root=newnode();
    }

    void insert(char buf[])
    {
        int len=strlen(buf);
        int now=root;
        for(int i=0;i<len;i++)
        {
            int k=buf[i]-'a';
            if(next[now][k]==-1)
                next[now][k]=newnode();
            now=next[now][k];
        }
        end[now]++;
    }

    void build()
    {
        queue<int> que;
        fail[root]=root;
        for(int i=0;i<N;i++)
            if(next[root][i]==-1)
                next[root][i]=root;
            else
            {
                fail[next[root][i]]=root;
                que.push(next[root][i]);
            }

        while(!que.empty())
        {
            int now = que.front();
            que.pop();
            for(int i=0;i<N;i++)
                if(next[now][i]==-1)
                    next[now][i]=next[fail[now]][i];
                else
                {
                    fail[next[now][i]]=next[fail[now]][i];
                    que.push(next[now][i]);
                }
        }
    }

    int query(char buf[])
    {
        int len=strlen(buf);
        int now=root;
        int res=0;
        for(int i=0;i<len;i++)
        {
            now=next[now][buf[i]-'a'];
            int temp=now;
            while(temp!=root)
            {
                res+=end[temp];
                end[temp]=0;
                temp=fail[temp];
            }
        }
        return res;
    }

};
Trie ac;
char temp[2][MAXN];
int main()
{
    //freopen("input.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,maxlen=0,point=0;
        scanf("%d",&n);
        ac.init();

        for(int i=0;i<n;i++)
        {
            scanf("%s",temp[point]);
            ac.insert(temp[point]);
            if(strlen(temp[point])>maxlen){
                maxlen=strlen(temp[point]);
                point=1-point;
            }
        }
        ac.build();
        int sum=ac.query(temp[1-point]);
        if(sum==n){
            printf("%s\n",temp[1-point]);
        }
        else {
            printf("No\n");
        }
    }

    return 0;
}

1001 Apple(HDU 6206)

这个题目是数学题,不背锅~大意是三个点确定一个圆,然后种第四个圆在三个圆的外接圆外输出Rejected,否则输出Accepted嗯!然后发现了比较好的讲解…

这里写图片描述

这里写图片描述

这里为了精确用乘法巧妙地去掉了除法,也比较好想,用java去搞(好久没做了…)

import java.math.*;
import java.util.*;
public class Main {
    public static void main(String args[]){
        int T;
        Scanner cin = new Scanner(System.in);
        T=cin.nextInt();
        while(T>0){
            BigDecimal Two =new BigDecimal(Double.toString(2.0));
            BigDecimal x1=cin.nextBigDecimal();
            BigDecimal y1=cin.nextBigDecimal();
            BigDecimal x2=cin.nextBigDecimal();
            BigDecimal y2=cin.nextBigDecimal();
            BigDecimal x3=cin.nextBigDecimal();
            BigDecimal y3=cin.nextBigDecimal();
            BigDecimal x=cin.nextBigDecimal();
            BigDecimal y=cin.nextBigDecimal();
            BigDecimal a=x1.subtract(x2);
            BigDecimal b=y1.subtract(y2);
            BigDecimal c=x1.subtract(x3);
            BigDecimal d=y1.subtract(y3);
            BigDecimal e=x1.multiply(x1).subtract(x2.multiply(x2)).subtract(y2.multiply(y2)).add(y1.multiply(y1));
            BigDecimal f=x1.multiply(x1).subtract(x3.multiply(x3)).subtract(y3.multiply(y3)).add(y1.multiply(y1));
            BigDecimal m=Two.multiply(a.multiply(d).subtract(b.multiply(c)));
            BigDecimal OX=d.multiply(e).subtract(b.multiply(f));
            BigDecimal OY=a.multiply(f).subtract(c.multiply(e));
            BigDecimal R=x1.multiply(m).subtract(OX).multiply(x1.multiply(m).subtract(OX)).add(y1.multiply(m).subtract(OY).multiply(y1.multiply(m).subtract(OY)));
            BigDecimal r=x.multiply(m).subtract(OX).multiply(x.multiply(m).subtract(OX)).add(y.multiply(m).subtract(OY).multiply(y.multiply(m).subtract(OY)));
            if (r.compareTo(R)==0||r.compareTo(R)<0){
                System.out.println("Rejected");
            }
            else {
                System.out.println("Accepted");
            }
            T-=1;
        }
        cin.close();
    }
}

1010 Brute Force Sorting

然后这个是水题中的蜜汁题目了,轻松可以想到是双向链表维护一下就可以,但是呢数据规模需要考虑,如果是纯模拟就是n^2的复杂的,所以说我们需要优化一下

考虑道题目,当我们去掉一个串后(假设是i-j),需要考虑的是i-1有没有在和j+1结合后出现没有sorted的串就好,至于i-1之前可能都是排序好了,不需要再去判断。这样我们用一个队列维护,每入队列的是去掉某串后,该串第一个字母的前一个节点(也就是可能是新的unsorted 串首字母的位置),不知道说清楚没总之就是酱,然后注意判断边界~

#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;
typedef struct node{
    int value;
    int pre,next,flag;
}node;
node a[100005];
queue<int> qqq;
int main(){
    //freopen("input.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i].value);
            a[i].pre=i-1;
            a[i].next=i+1;
            a[i].flag=1;
        }
        a[0].value=a[1].value;          //附两个边界值 
        a[0].next=1;
        a[n+1].value=a[n].value;
        a[n+1].pre=n;
        for(int i=1;i<=n;i++){
            if(a[i].flag==1&&(a[i].value<a[i-1].value||a[i].value>a[i+1].value)){   //找到不匹配的值,因为是第一遍找一定不存在边界情况,而且此刻每一个元素前一个点都是坐标减一 
                int start=i,pos=i;
                while(pos<=n){
                    if(a[pos].value<a[pos-1].value||a[pos].value>a[pos+1].value){
                        if(pos==n&&a[pos].value>=a[pos-1].value) {a[start-1].next=n;a[n].pre=start-1;break;} //需要考虑右边界 ,而且注意每次unsorted串匹配完了维护二向链表 
                        if(pos==n){a[start-1].next=n+1;a[n+1].pre=start-1;}
                        a[pos].flag=0;  //标记已经去掉了 
                        pos++;
                    }
                    else {
                        i=pos;
                        a[start-1].next=pos;
                        a[pos].pre=start-1;
                        break;
                    }
                }
                if(start-1!=0){         //如果不是第0个边界节点那么入队列 
                    qqq.push(start-1);
                }
            }
        }

        while(!qqq.empty()){        //开始清空队列 
            int start=qqq.front();  //取出个可能的值 
            qqq.pop();
            int pos=start;
            if(a[pos].value<=a[a[pos].next].value) continue;    //如果和下一个匹配那么直接跳过就好了 
            while(1){
                if(a[pos].flag==1&&(a[pos].value>a[a[pos].next].value||a[pos].value<a[a[pos].pre].value)){
                    if(a[pos].next==n+1&&a[pos].value>=a[a[pos].pre].value){//边界情况,但是注意边界情况需要维护链表 
                        a[a[start].pre].next=pos;
                        a[pos].pre=a[start].pre;
                        qqq.push(a[start].pre);
                        break;
                    }
                    if(a[pos].next==n+1){//边界情况,但是除了注意边界情况需要维护链表,还需要将头入队列了 
                        a[pos].flag=0;
                        a[a[start].pre].next=n+1;
                        a[n+1].pre=a[start].pre;
                        qqq.push(a[start].pre);
                        break;
                    }
                    a[pos].flag=0;
                    pos=a[pos].next;
                }
                else{       //匹配到合法项结束unsorted串匹配 
                    a[a[start].pre].next=pos;
                    a[pos].pre=a[start].pre;
                    if(a[start].pre!=0){    //如果不是开头入队列 
                        qqq.push(a[start].pre);
                    }
                    break;
                }
            }
        }
        int answer[100005],sum=0;
        for(int i=1;i<=n;i++){
            if(a[i].flag==1){
                answer[sum++]=a[i].value;
            }
        }
        cout<<sum<<endl;
        for(int i=0;i<sum;i++){
            cout<<answer[i]<<" ";
        }
        cout<<endl;
    }
    return 0; 
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值