太菜了….没办法….都要准备退水了,简单记录一下吧
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;
}