• 3976. 【NOI2015模拟1.17】⑨


    题目大意

    Cirno闲着无事的时候喜欢冰冻青蛙。
    Cirno每次从雾之湖中固定的n个结点中选出一些点构成一个简单多边形,Cirno运用自己的能力能将此多边形内所有青蛙冰冻。
    雾之湖生活着m只青蛙,青蛙有大有小,所以每只青蛙的价值为一个不大于10000的正整数。
    Cirno很想知道每次冻住的青蛙的价值总和。因为智商有限,Cirno将这个问题交给完美算术教室里的你。
    因为爱护动物,所以每次冻结的青蛙会被放生。也就是说一只青蛙可以被多次统计。

    对于30%的数据,n,m<=100; q<=100
    对于60%的数据,n,m<=100; q<=10000
    对于100%的数据,n,m<=1000; q<=10000
    -10000<=x,y<=10000; 0<v<=10000
    对于所有n+m个结点,保证不存在三点共线情况。

    题解

    读入优化没读负号居然只挂了40

    若干种做法

    第一种:

    按照求多边形面积的做法,先移到第一象限,然后求OAB里面点的权值和

    把线段变成直线分成七块,转为求一个点+一段夹角区间内的点,排序统计

    第二种:

    把第一种的求法变一下,延长AB交x轴与C,求OAC-OBC,枚举一个点以及一条射线统计

    第三种:

    求面积的时候求线段往下投影形成的梯形面积,计算这里面的权值

    枚举一个点以及一条射线,分左右讨论,在梯形里面的一定是斜率在射线前并且x在一定范围,排序+线段树

    虽然没有三点共线但是还是会有两个点在同一条垂线上,把所有点旋转1°即可

    code

    第一种

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define abs(x) ((x)>0?(x):-(x))
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    #define ll long long
    #define E 0.0000001
    //#define file
    using namespace std;
    
    struct type{int x,y,s;} b[1001],c[1001];
    struct Type{double S;int s;} a[2001];
    int f1[1001][1001],f2[1001][1001],f3[1001][1001],d[1001],n,m,Q,i,j,k,l,tot,mn1,mn2,Sum,sum,ans;
    double S;
    char ch;
    
    void Read(int &x) {int k=1;x=0; ch=getchar(); while (ch<'0' || ch>'9') k=(ch=='-')?-1:k,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+(ch-'0'),ch=getchar();x*=k;}
    bool cmp(Type a,Type b) {return a.S<b.S;}
    ll cj(type a,type b) {return b.x*a.y-a.x*b.y;}
    double js(type a)
    {
    	if (abs(a.y)<=E)
    	{
    		if (a.x>0) return 0;
    		else return M_PI;
    	}
    	if (abs(a.x)<=E)
    	{
    		if (a.y>0) return M_PI/2;
    		else return M_PI*3/2;
    	}
    	if (a.y>0) return atan2(a.y,a.x);
    	else return atan2(a.y,a.x)+M_PI*2;
    }
    double turn(double s)
    {
    	if (s<0) s+=M_PI*2;
    	if (s>M_PI*2) s-=M_PI*2;
    	return s;
    }
    
    void work1()
    {
    	tot=0;
    	fo(i,1,n) a[++tot]={js(b[i]),-i};
    	fo(i,1,m) a[++tot]={js(c[i]),c[i].s};
    	sort(a+1,a+tot+1,cmp);
    	fo(i,1,tot)
    	if (a[i].s<0)
    	{
    		sum=0;
    		fd(j,i,1)
    		if (a[j].s<0)
    		f1[-a[i].s][-a[j].s]=f1[-a[j].s][-a[i].s]=sum;
    		else
    		sum+=a[j].s;
    	}
    }
    void work2()
    {
    	fo(i,1,n)
    	{
    		S=js({-b[i].x,-b[i].y});
    		tot=0;
    		fo(j,1,n)
    		if (i!=j) a[++tot]={js({b[j].x-b[i].x,b[j].y-b[i].y}),-j};
    		fo(j,1,m) a[++tot]={js({c[j].x-b[i].x,c[j].y-b[i].y}),c[j].s};
    		fo(j,1,tot) a[j].S=turn(a[j].S-S);
    		
    		sort(a+1,a+tot+1,cmp);
    		sum=0;
    		fo(j,1,tot)
    		if (a[j].S<=M_PI)
    		{
    			if (a[j].s<0)
    			f2[i][-a[j].s]=(abs(a[j].S-M_PI)<E)?0:sum;
    			else
    			sum+=a[j].s;
    		}
    		else break;
    		k=j,sum=0;
    		fd(j,tot,k)
    		{
    			if (a[j].s<0)
    			f2[i][-a[j].s]=(abs(a[j].S-M_PI)<E)?0:sum;
    			else
    			sum+=a[j].s;
    		}
    	}
    }
    void work3()
    {
    	fo(i,1,n)
    	{
    		S=js({b[i].x,b[i].y});
    		tot=0;
    		fo(j,1,n)
    		if (i!=j) a[++tot]={js({b[i].x-b[j].x,b[i].y-b[j].y}),-j};
    		fo(j,1,m) a[++tot]={js({c[j].x-b[i].x,c[j].y-b[i].y}),c[j].s};
    		fo(j,1,tot) a[j].S=turn(a[j].S-S);
    		
    		sort(a+1,a+tot+1,cmp);
    		sum=0;
    		fo(j,1,tot)
    		if (a[j].S<=M_PI)
    		{
    			if (a[j].s<0)
    			f3[i][-a[j].s]=(abs(a[j].S-M_PI)<E)?0:sum;
    			else
    			sum+=a[j].s;
    		}
    		else break;
    		k=j,sum=0;
    		fd(j,tot,k)
    		{
    			if (a[j].s<0)
    			f3[i][-a[j].s]=(abs(a[j].S-M_PI)<E)?0:sum;
    			else
    			sum+=a[j].s;
    		}
    	}
    }
    
    int Js(int x,int y)
    {
    	int s=cj(b[x],b[y]);
    	if (!s) return 0;
    	else return (f1[x][y]+f2[x][y]+f3[x][y]+f2[y][x]+f3[y][x]-Sum)*((s>0)?1:-1);
    }
    
    int main()
    {
    	#ifdef file
    	freopen("a.in","r",stdin);
    	#endif
    	
    	Read(n),Read(m),mn1=mn2=2147483647;
    	fo(i,1,n) Read(b[i].x),Read(b[i].y),mn1=min(mn1,b[i].x),mn2=min(mn2,b[i].y);
    	fo(i,1,m) Read(c[i].x),Read(c[i].y),Read(c[i].s),Sum+=c[i].s,mn1=min(mn1,c[i].x),mn2=min(mn2,c[i].y);
    	--mn1,--mn2;
    	fo(i,1,n) b[i].x-=mn1,b[i].y-=mn2;
    	fo(i,1,m) c[i].x-=mn1,c[i].y-=mn2;
    	
    	work1();
    	work2();
    	work3();
    	
    	Read(Q);
    	for (;Q;--Q)
    	{
    		Read(l);
    		fo(i,1,l) Read(d[i]);
    		
    		ans=0;
    		fo(i,1,l-1) ans+=Js(d[i],d[i+1]);ans+=Js(d[l],d[1]);
    		ans=abs(ans);
    		printf("%d
    ",ans/2);
    	}
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    element-ui 设置input的只读或禁用
    vue 获取后端数据打印结果undefined问题
    用yaml来编写配置文件
    [LeetCode] 28. 实现strStr()
    [LeetCode] 25. k个一组翻转链表
    [LeetCode] 26. 删除排序数组中的重复项
    [LeetCode] 24. 两两交换链表中的节点
    [LeetCode] 23. 合并K个排序链表
    [LeetCode] 21. 合并两个有序链表
    [LeetCode] 22. 括号生成
  • 原文地址:https://www.cnblogs.com/gmh77/p/13735476.html
Copyright © 2020-2023  润新知