2020HDU多校第八场By Rynar 6855-6866

1003.Clockwise or Counterclockwise

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node{
    ll x,y;
}a[10];
ll xj(node a,node b){
    return a.x*b.y-a.y*b.x;
}
signed main(){
    int T;
    scanf("%d",&T);
    while (T--){
        for (int i=1;i<=3;i++)scanf("%lld%lld",&a[i].x,&a[i].y);
        ll ans=0;
        ans=xj(a[1],a[2])+xj(a[2],a[3])+xj(a[3],a[1]);//面积的一半
        if (ans<0)puts("Clockwise");
        else puts("Counterclockwise");
    }
    return 0;
}

1004.Discovery of Cycles

思路:LCT
赛时:心态爆炸,%m+1看成了%(m+1),最后没过,赛后改了一下就ac了

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int c[N][2],st[N],fa[N],rev[N],v[N];
int p[N],mn[N],q,kind,n,m,lastans,x,y;
struct use{int st,en;}e[N<<1];
struct node{
    int l,r;
    friend bool operator<(const node &a,const node &b){
        return a.r<b.r;
    }
}a[N];
int b[N];
bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
void updata(int x){
    int l=c[x][0],r=c[x][1];mn[x]=x;
    if (v[mn[l]]<v[mn[x]]) mn[x]=mn[l];
    if (v[mn[r]]<v[mn[x]]) mn[x]=mn[r];
}
void pushdown(int x){
    int l=c[x][0],r=c[x][1];
    if (rev[x]){
        rev[l]^=1;rev[r]^=1;rev[x]^=1;
        swap(c[x][0],c[x][1]);
    }
}
void rotata(int x){
    int y=fa[x],z=fa[y],l,r;
    if (c[y][0]==x) l=0;else l=1;r=l^1;
    if (!isroot(y)){if (c[z][0]==y)c[z][0]=x;else c[z][1]=x;}
    fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
    c[y][l]=c[x][r];c[x][r]=y;
    updata(y);updata(x);
}
void splay(int x){
    int top(0);st[++top]=x;
    for (int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
    for (int i=top;i;i--) pushdown(st[i]);
    while (!isroot(x)){
        int y=fa[x],z=fa[y];
        if (!isroot(y)){
            if (c[y][0]==x^c[z][0]==y) rotata(x);
            else rotata(y);
        }
        rotata(x);
    }
}
void access(int x){int t(0);while (x){splay(x);c[x][1]=t;t=x;updata(x);x=fa[x];}}
void makeroot(int x){access(x);splay(x);rev[x]^=1;}
void link(int x,int y){makeroot(x);fa[x]=y;}
void cut(int x,int y){makeroot(x);access(y);splay(y);c[y][0]=fa[x]=0;}
int que(int x,int y){makeroot(y);access(x);splay(x);return mn[x];}
int find(int x){
    access(x);splay(x);
    int y=x;
    while (c[y][0]) y=c[y][0];
    return y;
}
void pre(){
    int num=n;
    for (int i=1;i<=m;i++){
        int x=e[i].st,y=e[i].en;
        if (x==y) {p[i]=i;continue;} 
        if (find(x)==find(y)){
            int u=que(x,y),t=v[u];
            p[i]=t;cut(e[t].st,u);cut(e[t].en,u);
        }
        v[++num]=i;mn[num]=num;
        link(x,num);link(y,num);
    }
}
struct node1{
    int val,lazy;
    int l,r;
}tr[N<<2];
void pushup1(int rt){
    tr[rt].val=max(tr[rt<<1].val,tr[rt<<1|1].val);
}
void putdown1(int rt){
    if(tr[rt].lazy){
        tr[rt<<1].lazy=tr[rt<<1|1].lazy=tr[rt].lazy;
        tr[rt<<1].val=tr[rt<<1|1].val=tr[rt].lazy;
        tr[rt].lazy=0;
    }
}
void build1(int l,int r,int rt){
    tr[rt].l=l;
    tr[rt].r=r;
    tr[rt].lazy=0;
    if (l==r){
        tr[rt].val=a[l].l;
        return;
    }
    int mid=(l+r)>>1;
    build1(l,mid,rt<<1);
    build1(mid+1,r,rt<<1|1);
    pushup1(rt);
}
void update1(int l,int r,int add,int rt){
    if (l<=tr[rt].l&&r>=tr[rt].r){
        tr[rt].lazy=add;
        tr[rt].val=add;
        return;
    }
    putdown1(rt);
    if(l<=tr[rt<<1].r)
        update1(l,r,add,rt<<1);
    if(r>=tr[rt<<1|1].l)
        update1(l,r,add,rt<<1|1);
    pushup1(rt);
}
int query1(int l,int r,int rt){
    if(l==tr[rt].l&&r==tr[rt].r)
        return tr[rt].val;
    putdown1(rt);
    if(l>=tr[rt<<1|1].l)
        return query1(l,r,rt<<1|1);
    else if(r<=tr[rt<<1].r)
        return query1(l,r,rt<<1);
    else
        return max(query1(l,tr[rt<<1].r,rt<<1),query1(tr[rt<<1|1].l,r,rt<<1|1));
}
int cnt=0;
void solve(int x,int y){
    if (lastans!=-1)x=(x^lastans)%m+1,y=(y^lastans)%m+1;
    if (x>y)swap(x,y);
    lastans=0;
    int t=upper_bound(b+1,b+1+cnt,y)-b-1;
    if (t>0&&query1(1,t,1)>=x)lastans=1;
    if (lastans==1)puts("Yes");
    else puts("No");
}
int main(){
    int T;
    scanf("%d",&T);
    while (T--){
        lastans=-1;
        memset(c,0,sizeof c);
        memset(st,0,sizeof st);
        memset(fa,0,sizeof fa);
        memset(v,0x3f,sizeof(v));
        memset(rev,0,sizeof rev);
        memset(p,0,sizeof p);
        memset(mn,0,sizeof mn);
        scanf("%d%d%d",&n,&m,&q);
        for (int i=0;i<=n+m;i++)mn[i]=i;
        for (int i=1;i<=m;i++){
            scanf("%d%d",&e[i].st,&e[i].en);
        }
        pre();
        cnt=0;
        bool f=0;
        for (int i=1;i<=m;i++){
            if (p[i])a[++cnt].l=p[i],a[cnt].r=i,f=1;
        }
        sort(a+1,a+1+cnt);
        for (int i=1;i<=cnt;i++){
            b[i]=a[i].r;
        }
        build1(1,cnt,1);
        for (int i=1;i<=q;i++){
            scanf("%d%d",&x,&y);
            if (!f){
                puts("No");continue;
            }
            solve(x,y);
        }
    }
}

赛后

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
struct LCT{
    int tr[N],val[N],fa[N],son[N][2],rev[N];
    int top,sta[N];
    bool isroot(int t){
        return t!=son[fa[t]][0]&&t!=son[fa[t]][1];
    }
    bool isson(int t){return t==son[fa[t]][1];}
    void update(int t){
        tr[t]=tr[son[t][0]]^tr[son[t][1]]^val[t];
    }
    void pushdown(int t){
        if (rev[t]){
            rev[son[t][0]]^=1,rev[son[t][1]]^=1;
            swap(son[t][0],son[t][1]);
            rev[t]=0;
        }
    }
    void rotate(int t){
        int f=fa[t],g=fa[f],fis=isson(f),tis=isson(t);
        fa[t]=g;
        if (!isroot(f)) son[g][fis]=t;
        fa[son[t][tis^1]]=f,son[f][tis]=son[t][tis^1];
        fa[f]=t,son[t][tis^1]=f;
        update(f),update(t);
    }
    void splay(int t){
        sta[top=1]=t;
        int x=t;
        while (!isroot(x))x=fa[x],sta[++top]=x;
        while (top)pushdown(sta[top--]);
        while (!isroot(t)){
            int f=fa[t];
            if(isroot(f))rotate(t);
            else if(isson(f)==isson(t))rotate(f),rotate(t);
            else rotate(t),rotate(t);
        }
        update(t);
    }
    void access(int t){//访问
        for(int i=0;t;i=t,t=fa[t])
            splay(t),son[t][1]=i,update(t);
    }
    void makeroot(int t){//换根
        access(t),splay(t),rev[t]^=1;
    }
    int findroot(int t){//找根(在真实的树中的)
        access(t),splay(t);
        while(son[t][0])pushdown(t),t=son[t][0];
        splay(t);
        return t;
    }
    void split(int u,int v){//提取路径
        makeroot(v),access(u),splay(u);
    }
    void link(int u,int v){//连边
        makeroot(u);
        if (findroot(v)!=u)fa[u]=v;
    }
    void cut(int u,int v){//断边
        split(u,v);
        if (son[u][0]==v&&!son[v][1])son[u][0]=0,fa[v]=0;
    }
}lct;
int u[N],v[N];
int a[N];
int main(){
    int T,n,m,q,l,r,lastans;
    scanf("%d",&T);
    while (T--){
        scanf("%d%d%d",&n,&m,&q);
        for (int i=1;i<=m;i++){
            scanf("%d%d",&u[i],&v[i]);
            a[i]=0;
        }
        int l=1;
        for (int i=1;i<=m;i++){
            int xx=lct.findroot(u[i]),yy=lct.findroot(v[i]);
            while(xx==yy&&l<=i){
                a[l]=i;
                if (l!=i)lct.cut(u[l],v[l]);
                xx=lct.findroot(u[i]),yy=lct.findroot(v[i]);
                l++;
            }
            if (l!=i+1)lct.link(u[i],v[i]);
        }
        for (int i=l;i<=m;i++)lct.cut(u[i],v[i]);
        lastans=-1;
        while (q--){
            scanf("%d%d",&l,&r);
            if (lastans!=-1)l=(l^lastans)%m+1,r=(r^lastans)%m+1;
            if (l>r)swap(l,r);
            if (a[l]!=0&&a[l]<=r)puts("Yes"),lastans=1;
            else puts("No"),lastans=0;
        }
    }
    return 0;
}

1006.Fluctuation Limit

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n;
struct node{
    int l,r;
}a[N];
int l[N],r[N];
signed main(){
    int T,x;
    scanf("%d",&T);
    while (T--){
        scanf("%d%d",&n,&k);
        for (int i=1;i<=n;i++)scanf("%d%d",&a[i].l,&a[i].r);
        l[1]=a[1].l,r[1]=a[1].r;
        bool f=0;
        for (int i=2;i<=n;i++){//左到右
            l[i]=l[i-1]-k;r[i]=r[i-1]+k;
            if (a[i].l>r[i]||a[i].r<l[i]){
                f=1;break;
            }
            r[i]=min(r[i],a[i].r);
            l[i]=max(l[i],a[i].l);
        }
        for (int i=n-1;i>=1;i--){//右到左
            l[i]=max(l[i],l[i+1]-k);r[i]=min(r[i],r[i+1]+k);
            r[i]=min(r[i],a[i].r);
            l[i]=max(l[i],a[i].l);
        }
        if (f){
            puts("No");continue;
        }
        puts("Yes");
        int x=-1e9;
        for (int i=1;i<=n;i++){
            if (i!=1)printf(" ");
            x=max(x-k,l[i]);
            printf("%d",x);
        }
        puts("");
    }
    return 0;
}

1008.Hexagon

#include<bits/stdc++.h>
using namespace std;
int a[7]={0,5,6,1,2,3,4};
signed main(){
    int T,n,x;
    scanf("%d",&T);
    while (T--){
        scanf("%d",&n);
        while (n>2){
            int p=n-2;
            printf("6");
            for (int i=1;i<=6;i++){
                printf("%d",i);
                for (int j=1;j<=p-(i==6);j++){
                    printf("%d%d",a[i],i);
                }
            }
            printf("1");
            n-=2;
        }
        if(n==2)printf("612346");
        puts("");
    }
    return 0;
}

1009.Isomorphic Strings

思路:kmp O(nsqrt(n))

#include<bits/stdc++.h>
using namespace std;
const int N=1e7+10;
int n,m,k,d,r;
char s[N];
int nx[N];
int kmp(){
    int i=r,j=0;
    int len1=r+d*2,len2=d;
    while (i<len1&&j<len2){
        if (j==-1||s[(i-r)%d+r]==s[j])i++,j++;
        else j=nx[j];
    }
    if (j==len2)return i-j;
    else return -1;
}
void getnext(){//nx数组表示前后缀最长的相等串的长度
    int len=n;
    nx[0]=-1;
    int k=-1,j=0;
    while (j<len){
        if (k==-1||s[j]==s[k]){//p[k]表示前缀,p[j]表示后缀
            nx[++j]=++k;
        }
        else k=nx[k];
    }
}
signed main(){
    int T,x;
    scanf("%d",&T);
    while (T--){
        scanf("%d%s",&n,s);
        getnext();
        bool f=1;
        for (int k=1;k*k<=n;k++){
            if (n%k)continue;
            d=k;if (d==n)continue;
            f=0;
            for (int i=d;i<n;i+=d){
                r=i;
                if (kmp()==-1){
                    f=1;
                    break;
                }
            }
            if (f==0)break;
            d=n/k;if (d==n)continue;
            f=0;
            for (int i=d;i<n;i+=d){
                r=i;
                if (kmp()==-1){
                    f=1;
                    break;
                }
            }
            if (f==0)break;
        }
        if (f==0)puts("Yes");else puts("No");
    }
    return 0;
}

1011.Kidnapper's Matching Problem

思路:线性基+kmp

#include<bits/stdc++.h>
using namespace std;
const int maxn=30;
const int N=2e5+10;
const int mod=1e9+7;
int n,m,k;
int q[maxn+1];
int a[N],b[N],nx[N];
int kmp(){
    int i=0,j=0,p=1,ans=0;
    while (i<n){
        if (j==-1||a[i]==b[j]){
            if (i>=m)p=2ll*p%mod;
            i++,j++;
        }
        else j=nx[j];
        if(j==m){
            ans=(1ll*ans+p)%mod;
            j=nx[j];
        }
    }
    return ans;
}
void getnext(){//nx数组表示前后缀最长的相等串的长度
    nx[0]=-1;
    int k=-1,j=0;
    while (j<m){
        if (k==-1||b[j]==b[k]){
            nx[++j]=++k;
        }
        else k=nx[k];
    }
}
void get_lb(int x){
    for(int i=maxn;i>=0;i--){
        if (!(x>>i))continue;
        if (!q[i]){
            q[i]=x;break;
        }
        x^=q[i];
    }
}
int get(int x){//消除a,b在S中的bit位
    for (int i=maxn;i>=0;i--){
        if (x>>i&1)x^=q[i];
    }
    return x;
}
signed main(){
    int T,x;
    scanf("%d",&T);
    while (T--){
        scanf("%d%d%d",&n,&m,&k);
        for (int i=0;i<n;i++)scanf("%d",&a[i]);
        for (int i=0;i<m;i++)scanf("%d",&b[i]);
        memset(q,0,sizeof q);
        for (int i=0;i<k;i++){
            scanf("%d",&x);
            get_lb(x);
        }
        for (int i=0;i<n;i++)a[i]=get(a[i]);
        for (int i=0;i<m;i++)b[i]=get(b[i]);
        getnext();
        int ans=kmp();
        printf("%d\n",ans);
    }
    return 0;
}

1012.Linuber File System

思路:一定存在一种最优解,使得每个点的它和它所有祖先的操作值之和为li或ri之一或者0

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e3+10;
const int inf=0x3f3f3f3f;
int n,m,cnt;
vector<int>v[N];
int l[N],r[N],p[N];
int dp[N][N];//dp[i][j]为i节点,其父亲及以上具有j个操作值的操作次数
int pre[N],suf[N];
void dfs(int x,int fa){
    for (int i=1;i<=cnt;i++)dp[x][i]=0;
    for (int i:v[x]){
        if (i==fa)continue;
        dfs(i,x);
        for(int j=1;j<=cnt;j++){
            dp[x][j]+=dp[i][j];
        }
    }
    pre[0]=suf[cnt+1]=inf;
    for(int i=1;i<=cnt;i++){
        pre[i]=min(pre[i-1],((p[i]>=l[x]&&p[i]<=r[x])?dp[x][i]:inf));
    }
    for(int i=cnt;i>=1;i--){
        suf[i]=min(suf[i+1],((p[i]>=l[x]&&p[i]<=r[x])?dp[x][i]:inf));
    }
    for(int i=1;i<=cnt;i++){
        dp[x][i]=min(((p[i]>=l[x]&&p[i]<=r[x])?dp[x][i]:inf),min(pre[i-1],suf[i+1])+1);
    }
}
signed main(){
    int T,x,y;scanf("%d",&T);
    while (T--){
        scanf("%d",&n);
        for (int i=1;i<=n;i++)v[i].clear();
        for (int i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            v[x].push_back(y);v[y].push_back(x);
        }
        cnt=0;
        for (int i=1;i<=n;i++){
            scanf("%d%d",&l[i],&r[i]);
            p[++cnt]=l[i];p[++cnt]=r[i];
        }
        p[++cnt]=0;
        sort(p+1,p+1+cnt);
        cnt=unique(p+1,p+1+cnt)-p-1;
        dfs(1,0);
        int pos=lower_bound(p+1,p+cnt+1,0)-p;
        cout<<dp[1][pos]<<endl;
    }
    return 0;
}
posted @ 2020-08-13 18:58  Rynar  阅读(363)  评论(0)    收藏  举报