1.k个横着的障碍物(均在x轴上方),n个关健点(均在x轴上方),m个询问,问在某个坐标能看到多少个关键点(均在x轴下方)。k≤50,n,m≤100000,强制在线。

我只能说障碍物的两个端点很重要,因为它是许多关键直线的交点。这样判断一个点左侧有多少直线就只和与端点的连线的倾斜角有关了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long int ll;
 4 const int maxn=1E5+5;
 5 int n,k,op,m,lastans;
 6 struct pt
 7 {
 8     ll x,y;
 9     int num;
10     pt(ll a=0,ll b=0,int c=0):x(a),y(b),num(c){}
11     pt operator+(const pt&A){return pt(x+A.x,y+A.y);}
12     pt operator-(const pt&A){return pt(x-A.x,y-A.y);}
13     ll operator*(const pt&A){return x*A.y-y*A.x;}
14     bool operator<(const pt&A)const{return x*A.y-y*A.x<0;}
15     bool operator<=(const pt&A)const{return x*A.y-y*A.x<=0;}
16 }A[maxn],B[maxn][2];
17 vector<pt>wait[55][2];
18 inline void solve(int num)
19 {
20     vector<pt>V;
21     for(int i=1;i<=k;++i)
22     {
23         pt x=B[i][0]-A[num],y=B[i][1]-A[num];
24         if(x.y>=0)
25             continue;
26         x.num=i,y.num=i+k;
27         V.push_back(x),V.push_back(y);
28     }
29     sort(V.begin(),V.end());
30     int g=0;
31     for(int i=0;i<V.size();++i)
32     {
33         pt x=V[i];
34         bool f1=g<0;
35         g+=x.num<=k?1:-1;
36         bool f2=g<0;
37         if(f1!=f2)
38         {
39             if(x.num<=k)
40                 wait[x.num][0].push_back(x);
41             else
42                 wait[x.num-k][1].push_back(x);
43         }
44     }
45 }
46 int main()
47 {
48     ios::sync_with_stdio(false);
49     cin>>n>>k>>m>>op;
50     for(int i=1;i<=n;++i)
51         cin>>A[i].x>>A[i].y;
52     for(int i=1;i<=k;++i)
53     {
54         int x,y,z;
55         cin>>x>>y>>z;
56         if(x>y)
57             swap(x,y);
58         B[i][0]=pt(x,z),B[i][1]=pt(y,z);
59     }
60     for(int i=1;i<=n;++i)
61         solve(i);
62     for(int i=1;i<=k;++i)
63     {
64         sort(wait[i][0].begin(),wait[i][0].end());
65         sort(wait[i][1].begin(),wait[i][1].end());
66         /*
67         cout<<"NOW "<<i<<endl;
68         for(auto p:wait[i][0])
69             cout<<p.x<<" "<<p.y<<endl;
70         cout<<endl;
71         for(auto p:wait[i][1])
72             cout<<p.x<<" "<<p.y<<endl;
73         cout<<endl;*/
74     }
75     for(int i=1;i<=m;++i)
76     {
77         int x,y;
78         cin>>x>>y;
79         if(op)
80             x^=lastans,y^=lastans;
81         int g=0;
82         for(int j=1;j<=k;++j)
83         {
84             g+=(wait[j][0].size())-(lower_bound(wait[j][0].begin(),wait[j][0].end(),pt(x,y)-B[j][0])-wait[j][0].begin());
85             g-=(wait[j][1].size())-(upper_bound(wait[j][1].begin(),wait[j][1].end(),pt(x,y)-B[j][1])-wait[j][1].begin());
86         }
87         lastans=n-g;
88         cout<<lastans<<endl;
89     }
90     return 0;
91 }
View Code

2.每次询问区间的所有子区间的mex,要求一个log,离线。

每次固定右端点r后,记在此之前出现的数字i的最右端点为b[i],没有这个数字那么b[i]为0。为了计算所有区间[i,r]的mex,我们执行下列操作:

  1.设pos=0。

  2.找到最大的k,使得k>pos且b[k]<b[pos]。那么左端点在区间[b[k]+1,b[pos]]中的 区间 的mex为k。

  3.重复2,直到b[pos]为0。

这相当于找到b中的一个连续下降的子序列,而每次修改b只会把一个数字变大。如果这个变大的数字在之前不存在于下降子序列中,那么没有影响。否则需要修改一个类似“阶梯”的形状。很容易知道修改的总次数是线性的。这样,我们需要支持一个能区间加法、历史所有值之和的数据结构。而历史所有值之和实际上是一次函数(例如,没有任何修改的话,对于时刻t,历史所有值之和为t*val),更关键的是,时间只会单调增(那么尽管加一个一次函数会对前面产生影响,对答案也不会产生影响)。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long int ll;
  4 const int maxn=1E6+5;
  5 int n,m,a[maxn],b[maxn],pre[maxn];
  6 ll ans[maxn];
  7 ll tmin[maxn*4],tk[maxn*4],tb[maxn*4],tlast[maxn*4];
  8 ll tagk[maxn*4],tagb[maxn*4];
  9 bool chosen[maxn];
 10 struct query
 11 {
 12     int l,r,id;
 13     bool operator<(const query&A)const
 14     {
 15         return r<A.r;
 16     }
 17 }Q[maxn];
 18 void changeDot(int l,int r,int pos,int x,int num)
 19 {
 20     if(l==r)
 21     {
 22         tmin[num]=x;
 23         return;
 24     }
 25     int mid=(l+r)>>1;
 26     if(pos<=mid)
 27         changeDot(l,mid,pos,x,num<<1);
 28     else
 29         changeDot(mid+1,r,pos,x,num<<1|1);
 30     tmin[num]=min(tmin[num<<1],tmin[num<<1|1]);
 31 }
 32 int find(int L,int R,int l,int r,int x,int num)
 33 {
 34     if(l==r)
 35     {
 36         if(tmin[num]>x)
 37             return -1;
 38         return l;
 39     }
 40     int mid=(l+r)>>1;
 41     if(L<=l&&r<=R)
 42     {
 43         if(tmin[num<<1]<=x)
 44             return find(L,R,l,mid,x,num<<1);
 45         return find(L,R,mid+1,r,x,num<<1|1);
 46     }
 47     if(R<=mid)
 48         return find(L,R,l,mid,x,num<<1);
 49     else if(mid<L)
 50         return find(L,R,mid+1,r,x,num<<1|1);
 51     int y=find(L,R,l,mid,x,num<<1);
 52     if(y==-1)
 53         return find(L,R,mid+1,r,x,num<<1|1);
 54     return y;
 55 }
 56 inline void put(int num,int l,int r,ll k,ll b)
 57 {
 58     tk[num]+=k*(r-l+1);
 59     tb[num]+=b*(r-l+1);
 60     tagk[num]+=k,tagb[num]+=b;
 61 }
 62 inline void pushdown(int num,int l,int r)
 63 {
 64     ll k=tagk[num],b=tagb[num];
 65     tagk[num]=tagb[num]=0;
 66     int mid=(l+r)>>1;
 67     put(num<<1,l,mid,k,b),put(num<<1|1,mid+1,r,k,b);
 68 }
 69 inline void pushup(int num)
 70 {
 71     tk[num]=tk[num<<1]+tk[num<<1|1];
 72     tb[num]=tb[num<<1]+tb[num<<1|1];
 73 }
 74 void add(int L,int R,int l,int r,ll k,ll b,int num)
 75 {
 76     if(L<=l&&r<=R)
 77     {
 78         put(num,l,r,k,b);
 79         return;
 80     }
 81     pushdown(num,l,r);
 82     int mid=(l+r)>>1;
 83     if(R<=mid)
 84         add(L,R,l,mid,k,b,num<<1);
 85     else if(mid<L)
 86         add(L,R,mid+1,r,k,b,num<<1|1);
 87     else
 88         add(L,R,l,mid,k,b,num<<1),add(L,R,mid+1,r,k,b,num<<1|1);
 89     pushup(num);
 90 }
 91 ll ask(int L,int R,int l,int r,int t,int num)
 92 {
 93     if(L<=l&&r<=R)
 94         return tk[num]*t+tb[num];
 95     pushdown(num,l,r);
 96     int mid=(l+r)>>1;
 97     if(R<=mid)
 98         return ask(L,R,l,mid,t,num<<1);
 99     else if(mid<L)
100         return ask(L,R,mid+1,r,t,num<<1|1);
101     return ask(L,R,l,mid,t,num<<1)+ask(L,R,mid+1,r,t,num<<1|1);
102 }
103 inline void insert(int now,int r,int l,int t)
104 {
105     if(t==0||r==0)
106         return;
107     if(l+1>r)
108         return;
109     assert(l+1<=r);
110     add(l+1,r,1,n,t,(ll)t-(ll)t*now,1);
111 }
112 inline void solve()
113 {
114     int pos=1;
115     chosen[0]=1;
116     for(int i=0;i<=n;++i)
117         pre[i]=-1;
118     for(int i=1;i<=n;++i)
119     {
120         a[i]=min(a[i],n);
121         if(a[i]==0||chosen[a[i]])
122         {
123             int last=b[a[i]],now=i;
124             if(pre[a[i]]!=-1)
125                 insert(i,b[pre[a[i]]],last,-a[i]);
126             int x=find(a[i]+1,n+1,0,n+1,last,1);
127             insert(i,last,b[x],-x);
128             chosen[a[i]]=0;
129             b[a[i]]=i;
130             changeDot(0,n+1,a[i],i,1);
131             int y=pre[a[i]];
132             if(y==-1)
133                 y=0;
134             x=find(a[i]+1,n+1,0,n+1,b[y],1);
135             for(;b[x]>last;x=find(x+1,n+1,0,n+1,b[x],1))
136             {
137                 if(y!=-1)
138                     insert(i,b[y],b[x],x);
139                 chosen[x]=1;
140                 pre[x]=y;
141                 y=x;
142             }
143             if(y!=-1)
144                 insert(i,b[y],b[x],x);
145             chosen[x]=1;
146             pre[x]=y;
147         }
148         b[a[i]]=i;
149         changeDot(0,n+1,a[i],i,1);
150         while(pos<=m&&Q[pos].r==i)
151         {
152             ans[Q[pos].id]=ask(Q[pos].l,i,1,n,i,1);
153             ++pos;
154         }
155     }
156 }
157 int main()
158 {
159     ios::sync_with_stdio(false);
160     int useless;
161     cin>>useless>>n;
162     for(int i=1;i<=n;++i)
163         cin>>a[i];
164     cin>>m;
165     for(int i=1;i<=m;++i)
166     {
167         cin>>Q[i].l>>Q[i].r;
168         Q[i].id=i;
169     }
170     sort(Q+1,Q+m+1);
171     solve();
172     for(int i=1;i<=m;++i)
173         cout<<ans[i]<<'\n';
174     return 0;
175 }
View Code

3.问一个串的本质不同的最小表示子串。

  1 #include<bits/stdc++.h>
  2 #define mod1 998244353
  3 #define p1 13131
  4 using namespace std;
  5 typedef unsigned long long ull;
  6 typedef long long int ll;
  7 const int maxn=1E5+5;
  8 const int base=1;
  9 int n;
 10 int tot,a[maxn],bucket[maxn],root[maxn],ls[maxn*20],rs[maxn*20],p[maxn];
 11 ull len1[maxn],len2[maxn],t[maxn*20];
 12 inline void init()
 13 {
 14     len1[0]=1;
 15     for(int i=1;i<=n;++i)
 16         len1[i]=len1[i-1]*p1;
 17     for(int i=0;i<=2000000;++i)
 18         t[i]=1;
 19 }
 20 void change(int l,int r,int pos,int x,int&num,int pre)
 21 {
 22     num=++tot;
 23     ls[num]=ls[pre],rs[num]=rs[pre];
 24     if(l==r)
 25     {
 26         t[num]=x;
 27         return;
 28     }
 29     int mid=(l+r)>>1;
 30     if(pos<=mid)
 31         change(l,mid,pos,x,ls[num],ls[pre]);
 32     else
 33         change(mid+1,r,pos,x,rs[num],rs[pre]);
 34     t[num]=(t[ls[num]]+t[rs[num]]*len1[mid-l+1]);
 35 }
 36 ll ask(int L,int R,int l,int r,int num)
 37 {
 38     if(L<=l&&r<=R)
 39         return t[num];
 40     int mid=(l+r)>>1;
 41     if(R<=mid)
 42         return ask(L,R,l,mid,ls[num]);
 43     else if(mid<L)
 44         return ask(L,R,mid+1,r,rs[num]);
 45     return (ask(L,R,l,mid,ls[num])+ask(L,R,mid+1,r,rs[num])*len1[mid-max(l,L)+1]);
 46 }
 47 int dot(int l,int r,int pos,int num)
 48 {
 49     if(l==r)
 50         return t[num];
 51     int mid=(l+r)>>1;
 52     if(pos<=mid)
 53         return dot(l,mid,pos,ls[num]);
 54     return dot(mid+1,r,pos,rs[num]);
 55 }
 56 inline int bound(int x,int y)
 57 {
 58     if(x>y)
 59         swap(x,y);
 60     int l=1,r=x,mid;
 61     while(l<r)
 62     {
 63         mid=(l+r+1)>>1;
 64         if(ask(x-mid+1,x,1,n,root[x])==ask(y-mid+1,y,1,n,root[y]))
 65             l=mid;
 66         else
 67             r=mid-1;
 68     }
 69     mid=(l+r+1)>>1;
 70     return mid;
 71 }
 72 inline bool cmp(int x,int y)
 73 {
 74     int len=bound(x,y);
 75     if(x<y)
 76     {
 77         if(x==len)
 78             return 1;
 79         int cx=dot(1,n,x-len,root[x]);
 80         int cy=dot(1,n,y-len,root[y]);
 81         return cx<cy;
 82     }
 83     else
 84     {
 85         if(y==len)
 86             return 0;
 87         int cx=dot(1,n,x-len,root[x]);
 88         int cy=dot(1,n,y-len,root[y]);
 89         return cx<cy;
 90     }
 91 }
 92 inline void out(int x)
 93 {
 94     for(int j=1;j<=n-x;++j)
 95         cout<<"  ";
 96     for(int j=1;j<=x;++j)
 97         cout<<dot(1,n,j,root[x])<<" ";cout<<endl;
 98 }
 99 int main()
100 {
101 //    freopen("waterflow7_0.in","r",stdin);
102     ios::sync_with_stdio(false);
103     cin>>n;
104     init();
105     for(int i=1;i<=n;++i)
106         cin>>a[i];
107     for(int i=1;i<=n;++i)
108     {
109         change(1,n,i,0+base,root[i],root[i-1]);
110         if(bucket[a[i]])
111             change(1,n,bucket[a[i]],i-bucket[a[i]]+base,root[i],root[i]);
112         bucket[a[i]]=i;
113     }
114     for(int i=1;i<=n;++i)
115         p[i]=i;
116     stable_sort(p+1,p+n+1,cmp);
117     ll ans=p[1];
118     for(int i=2;i<=n;++i)
119         ans+=p[i]-bound(p[i-1],p[i]);
120     cout<<ans<<endl;
121     return 0;
122 }
View Code

 

 posted on 2020-09-16 08:00  GreenDuck  阅读(144)  评论(0编辑  收藏  举报